mirror of
https://github.com/chinchang/web-maker.git
synced 2025-05-30 05:59:12 +02:00
commit
6fe592fa88
@ -37,4 +37,6 @@ chrome.runtime.onInstalled.addListener(function callback (details) {
|
||||
openApp();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
chrome.runtime.setUninstallURL('https://kushagragour.in/lab/web-maker/uninstall/');
|
142
src/index.html
142
src/index.html
@ -3,7 +3,9 @@
|
||||
<meta charset="utf-8">
|
||||
<title>Web Maker</title>
|
||||
<link rel="stylesheet" href="lib/codemirror/lib/codemirror.css">
|
||||
<link rel="stylesheet" href="lib/codemirror/theme/monokai.css">
|
||||
|
||||
<link rel="stylesheet" id="editorThemeLinkTag" href="/lib/codemirror/theme/monokai.css"></link>
|
||||
|
||||
<link rel="stylesheet" href="lib/codemirror/addon/hint/show-hint.css">
|
||||
<link rel="stylesheet" href="lib/codemirror/addon/fold/foldgutter.css">
|
||||
<link rel="stylesheet" href="lib/hint.min.css">
|
||||
@ -19,16 +21,16 @@
|
||||
Add library <span id="js-external-lib-count" style="display:none;" class="count-label"></span>
|
||||
</a>
|
||||
|
||||
<a id="newBtn" class="flex flex-v-center hint--bottom-left" aria-label="Start a new creation">
|
||||
<a class="flex flex-v-center hint--bottom-left" aria-label="Start a new creation" d-click="onNewBtnClick">
|
||||
<svg style="vertical-align:middle;width:14px;height:14px" viewBox="0 0 24 24">
|
||||
<path d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
|
||||
</svg>New
|
||||
</a>
|
||||
<a id="saveBtn" class="flex flex-v-center hint--bottom-left" aria-label="Save current creation (Ctrl/⌘ + S)">
|
||||
<a id="saveBtn" class="flex flex-v-center hint--bottom-left" aria-label="Save current creation (Ctrl/⌘ + S)" d-click="onSaveBtnClick">
|
||||
<svg style="vertical-align:middle;width:14px;height:14px" viewBox="0 0 24 24">
|
||||
<path d="M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z" />
|
||||
</svg>Save</a>
|
||||
<a id="openBtn" class="flex flex-v-center hint--bottom-left" aria-label="Open a saved creation (Ctrl/⌘ + O)">
|
||||
<a class="flex flex-v-center hint--bottom-left" aria-label="Open a saved creation (Ctrl/⌘ + O)" d-click="onOpenBtnClick">
|
||||
<svg style="width:14px;height:14px;vertical-align:middle;" viewBox="0 0 24 24">
|
||||
<path d="M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6Z" />
|
||||
</svg>Open
|
||||
@ -45,7 +47,7 @@
|
||||
<ul class="js-modes-menu dropdown__menu">
|
||||
<li><a data-type="html" data-mode="html">HTML</a></li>
|
||||
<li><a data-type="html" data-mode="markdown">Markdown</a></li>
|
||||
<li><a data-type="html" data-mode="jade">Jade</a></li>
|
||||
<li><a data-type="html" data-mode="jade">Pug</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="code-wrap__header-right-options">
|
||||
@ -175,9 +177,10 @@
|
||||
</div>
|
||||
|
||||
<div class="modal" id="addLibraryModal">
|
||||
<div class="modal__content" id="app">
|
||||
<div class="modal__content">
|
||||
<h1>Add Library</h1>
|
||||
<h3>JavaScript</h3>
|
||||
<p style="font-size: 0.8em;opacity: 0.7;">Note: You can load external scripts from following domains: localhost, https://ajax.googleapis.com, https://code.jquery.com, https://cdnjs.cloudflare.com, https://unpkg.com, https://maxcdn.com, https://cdn77.com, https://maxcdn.bootstrapcdn.com, https://cdn.jsdelivr.net/</p>
|
||||
<textarea id="js-external-js" class="full-width" id="" cols="30" rows="5" placeholder="Start typing name of a library. Put each library in new line"></textarea>
|
||||
|
||||
<h3>CSS</h3>
|
||||
@ -200,12 +203,13 @@
|
||||
|
||||
<div class="modal" id="helpModal">
|
||||
<div class="modal__content">
|
||||
<h1>Web Maker<small style="font-size:14px;"> v2.3.2</small></h1>
|
||||
<h1>Web Maker<small style="font-size:14px;"> v2.4.0</small></h1>
|
||||
<div>
|
||||
<p>Made with <span style="margin-right: 8px;">💖</span> & <span style="margin-right: 8px;">🙌</span> by <a href="https://twitter.com/chinchang457" target="_blank">Kushagra Gour</a></p>
|
||||
<p>Tweet out your feature requests, comments & suggestions to <a target="_blank" href="https://twitter.com/webmakerApp">@webmakerApp</a>.</p>
|
||||
<p>Like this extension? Please <a href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank">rate it here</a>.</p>
|
||||
<p>
|
||||
<a aria-label="Rate Web Maker" href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank" class="btn btn-icon"><svg><use xlink:href="#heart-icon"></use></svg>Show some love</a>
|
||||
<a aria-label="Report a Bug" href="https://github.com/chinchang/web-maker/issues" target="_blank" class="btn btn-icon"><svg><use xlink:href="#bug-icon"></use></svg>Report a Bug</a>
|
||||
<a aria-label="Contribute on Github" href="https://github.com/chinchang/web-maker" target="_blank" class="btn btn-icon"><svg><use xlink:href="#github-icon"></use></svg>Contribute on Github</a>.
|
||||
</p>
|
||||
@ -291,16 +295,120 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="settingsModal">
|
||||
<div class="modal__content">
|
||||
<h1>Settings</h1>
|
||||
|
||||
<h3>Indentation</h3>
|
||||
<p>
|
||||
<div class="line">
|
||||
<label>
|
||||
<input type="radio" checked="true" name="indentation" value="spaces" d-change="updateSetting" data-setting="indentWith"> Spaces
|
||||
</label>
|
||||
<label class="ml-1">
|
||||
<input type="radio" name="indentation" value="tabs" d-change="updateSetting" data-setting="indentWith"> Tabs
|
||||
</label>
|
||||
</div>
|
||||
<label class="line">
|
||||
Indentation Size <input type="range" class="va-m ml-1" value="2" min="1" max="7" list="indentationSizeList" data-setting="indentSize" d-change="updateSetting">
|
||||
<datalist id="indentationSizeList">
|
||||
<option>1</option>
|
||||
<option>2</option>
|
||||
<option>3</option>
|
||||
<option>4</option>
|
||||
<option>5</option>
|
||||
<option>6</option>
|
||||
<option>7</option>
|
||||
</datalist>
|
||||
</label>
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<h3>Editor</h3>
|
||||
<p>
|
||||
<label class="line">
|
||||
Default Preprocessors
|
||||
</label>
|
||||
<div class="flex line">
|
||||
<select style="flex:1;margin:0 20px" data-setting="htmlMode" d-change="updateSetting">
|
||||
<option value="html">HTML</option>
|
||||
<option value="markdown">Markdown</option>
|
||||
<option value="jade">Pug</option>
|
||||
</select>
|
||||
<select style="flex:1;margin:0 20px" data-setting="cssMode" d-change="updateSetting">
|
||||
<option value="css">CSS</option>
|
||||
<option value="scss">SCSS</option>
|
||||
<option value="sass">SASS</option>
|
||||
<option value="less">LESS</option>
|
||||
<option value="stylus">Stylus</option>
|
||||
</select>
|
||||
<select style="flex:1;margin:0 20px" data-setting="jsMode" d-change="updateSetting">
|
||||
<option value="js">JS</option>
|
||||
<option value="coffee">CoffeeScript</option>
|
||||
<option value="es6">ES6 (Babel)</option>
|
||||
<option value="typescript">TypeScript</option>
|
||||
</select>
|
||||
</div>
|
||||
<label class="line">
|
||||
Theme
|
||||
<select style="flex:1;margin:0 20px" data-setting="editorTheme" d-change="updateSetting"></select>
|
||||
</label>
|
||||
<label class="line">
|
||||
Font Size <input type="number" value="16" data-setting="fontSize" d-change="updateSetting"> px
|
||||
|
||||
</label>
|
||||
<div class="line">
|
||||
Key bindings
|
||||
<label class="ml-1">
|
||||
<input type="radio" checked="true" name="keymap" value="sublime" d-change="updateSetting" data-setting="keymap"> Sublime
|
||||
</label>
|
||||
<label class="ml-1">
|
||||
<input type="radio" name="keymap" value="vim" d-change="updateSetting" data-setting="keymap"> Vim
|
||||
</label>
|
||||
</div>
|
||||
<label class="line">
|
||||
<input type="checkbox" d-change="updateSetting" data-setting="preserveLastCode"> Preserve last written code
|
||||
</label>
|
||||
<label class="line">
|
||||
<input type="checkbox" d-change="updateSetting" data-setting="replaceNewTab"> Replace new tab page
|
||||
</label>
|
||||
</p>
|
||||
<hr>
|
||||
|
||||
<h3>Fun</h3>
|
||||
<p>
|
||||
<label class="line">
|
||||
<input type="checkbox" d-change="updateSetting" data-setting="isCodeBlastOn"> Code blast!
|
||||
</label>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="notificationsModal">
|
||||
<div class="modal__content">
|
||||
<h1>Whats new?</h1>
|
||||
<div class="notification">
|
||||
<span class="notification__version">2.4.0</span>
|
||||
<ul>
|
||||
<li><strong>Import/Export</strong>: Your creations are most important. Now export all your creations into a single file as a backup that can be imported anytime & anywhere.</li>
|
||||
<li><strong>Editor themes</strong>: You have been heard. Now you can choose from a huge list of wonderful editor themes!</li>
|
||||
<li><strong>Identation settings</strong>: Not a spaces fan? Switch to tabs and set your indentation size.</li>
|
||||
<li><strong>Vim key bindings</strong>: Rejoice Vim lovers!</li>
|
||||
<li><strong>Code blast</strong>: Why don't you try coding with this switched on from the settings? Go on...</li>
|
||||
<li><strong>Important</strong>: Due to security policy changes from Chrome 57 onwards, Web Maker now allows loading external JavaScript libraries only from certain whitelisted domains (localhost, https://ajax.googleapis.com, https://code.jquery.com, https://cdnjs.cloudflare.com, https://unpkg.com, https://maxcdn.com, https://cdn77.com, https://maxcdn.bootstrapcdn.com, https://cdn.jsdelivr.net/)</li>
|
||||
<li>Save button now highlights when you have unsaved changes.</li>
|
||||
<li>Jade is now called Pug. Just a name change.</li>
|
||||
|
||||
<li><a href="https://github.com/chinchang/web-maker/issues" target="_blank">Suggest features or report bugs.</a></li>
|
||||
<li>Thank you for being a part of this community of thousands of awesome developers. If you find Web Maker helpful, <a href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank" class="btn">Please rate Web Maker <span class="star"></span></a> & <a href="http://twitter.com/share?url=https://kushagragour.in/lab/web-maker/&text=Web Maker - A blazing fast %26 offline web playground! via @webmakerApp&related=webmakerApp&hashtags=web,editor,chrome,extension" target="_blank" target="_blank" class="btn">share it</a>.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="notification">
|
||||
<span class="notification__version">2.3.2</span>
|
||||
<ul>
|
||||
<li>Update Babel to support latest and coolest ES6 features.</li>
|
||||
<li>Improve onboarding experience at first install.</li>
|
||||
<li><a href="https://github.com/chinchang/web-maker/issues" target="_blank">Suggest features or report bugs.</a></li>
|
||||
<li>Thank you for being a part of this community of thousands of awesome developers. If you find Web Maker helpful, <a href="https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh/reviews" target="_blank" class="btn">Please rate Web Maker <span class="star"></span></a> & <a href="http://twitter.com/share?url=https://kushagragour.in/lab/web-maker/&text=Web Maker - A blazing fast %26 offline web playground! via @webmakerApp&related=webmakerApp&hashtags=web,editor,chrome,extension" target="_blank" target="_blank" class="btn">share it</a>.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="notification">
|
||||
@ -377,7 +485,16 @@
|
||||
|
||||
<div id="js-saved-items-pane" class="saved-items-pane">
|
||||
<button class="btn saved-items-pane__close-btn" id="js-saved-items-pane-close-btn">X</button>
|
||||
<h3>My Library</h3>
|
||||
<div class="flex flex-v-center" style="justify-content: space-between;">
|
||||
|
||||
<h3>My Library <span id="savedItemCountEl"></span></h3>
|
||||
<div class="main-header__btn-wrap">
|
||||
<a d-click="exportItems" href="" class="btn btn-icon">Export
|
||||
</a>
|
||||
<a d-click="onImportBtnClicked" href="" class="btn btn-icon">Import
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="js-saved-items-wrap" class="saved-items-pane__container">
|
||||
|
||||
</div>
|
||||
@ -419,6 +536,9 @@
|
||||
<symbol id="settings-icon" viewBox="0 0 24 24">
|
||||
<path d="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z"></path>
|
||||
</symbol>
|
||||
<symbol id="heart-icon" viewBox="0 0 24 24">
|
||||
<path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z" />
|
||||
</symbol>
|
||||
</svg>
|
||||
|
||||
<script src="lib/codemirror/lib/codemirror.js"></script>
|
||||
@ -445,7 +565,9 @@
|
||||
<script src="lib/codemirror/mode/css/css.js"></script>
|
||||
<script src="lib/codemirror/mode/htmlmixed/htmlmixed.js"></script>
|
||||
<script src="lib/codemirror/keymap/sublime.js"></script>
|
||||
<script src="lib/codemirror/keymap/vim.js"></script>
|
||||
<script src="lib/emmet.js"></script>
|
||||
<script src="lib/code-blast.js"></script>
|
||||
|
||||
<script src="lib/split.js"></script>
|
||||
<script src="lib/inlet.min.js"></script>
|
||||
|
222
src/lib/code-blast.js
Normal file
222
src/lib/code-blast.js
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
Based on Joel Besada's lovely experiment
|
||||
https://twitter.com/JoelBesada/status/670343885655293952
|
||||
*/
|
||||
|
||||
;(function () {
|
||||
var shakeTime = 0,
|
||||
shakeTimeMax = 0,
|
||||
shakeIntensity = 5,
|
||||
lastTime = 0,
|
||||
particles = [],
|
||||
particlePointer = 0,
|
||||
MAX_PARTICLES = 100,
|
||||
PARTICLE_NUM_RANGE = { min: 2, max: 7 },
|
||||
PARTICLE_GRAVITY = 0.08,
|
||||
PARTICLE_ALPHA_FADEOUT = 0.96,
|
||||
PARTICLE_VELOCITY_RANGE = {
|
||||
x: [-1, 1],
|
||||
y: [-3.5, -1.5]
|
||||
},
|
||||
w = window.innerWidth,
|
||||
h = window.innerHeight,
|
||||
effect,
|
||||
isActive = false;
|
||||
|
||||
var codemirrors = [], cmNode;
|
||||
var canvas, ctx;
|
||||
var current_time, dt, magnitude, shakeX, shakeY; // loop vars
|
||||
var throttledShake = throttle(shake, 100);
|
||||
var throttledSpawnParticles = throttle(spawnParticles, 100);
|
||||
|
||||
function getRGBComponents(node) {
|
||||
var color = getComputedStyle(node).color;
|
||||
if (color) {
|
||||
try {
|
||||
return color.match(/(\d+), (\d+), (\d+)/).slice(1);
|
||||
} catch(e) {
|
||||
return [255, 255, 255];
|
||||
}
|
||||
} else {
|
||||
return [255, 255, 255];
|
||||
}
|
||||
}
|
||||
|
||||
function spawnParticles(cm, type) {
|
||||
var cursorPos = cm.getCursor();
|
||||
var pos = cm.cursorCoords();
|
||||
var node = document.elementFromPoint(pos.left - 5, pos.top + 5);
|
||||
type = cm.getTokenAt(cursorPos);
|
||||
if (type) { type = type.type; };
|
||||
var numParticles = random(PARTICLE_NUM_RANGE.min, PARTICLE_NUM_RANGE.max);
|
||||
var color = getRGBComponents(node);
|
||||
for (var i = numParticles; i--;) {
|
||||
particles[particlePointer] = createParticle(pos.left + 10, pos.top, color);
|
||||
particlePointer = (particlePointer + 1) % MAX_PARTICLES;
|
||||
}
|
||||
}
|
||||
|
||||
function createParticle(x, y, color) {
|
||||
var p = {
|
||||
x: x,
|
||||
y: y + 10,
|
||||
alpha: 1,
|
||||
color: color
|
||||
};
|
||||
if (effect === 1) {
|
||||
p.size = random(2, 4);
|
||||
p.vx = PARTICLE_VELOCITY_RANGE.x[0] + Math.random() *
|
||||
(PARTICLE_VELOCITY_RANGE.x[1] - PARTICLE_VELOCITY_RANGE.x[0]);
|
||||
p.vy = PARTICLE_VELOCITY_RANGE.y[0] + Math.random() *
|
||||
(PARTICLE_VELOCITY_RANGE.y[1] - PARTICLE_VELOCITY_RANGE.y[0]);
|
||||
} else if (effect === 2) {
|
||||
p.size = random(2, 8);
|
||||
p.drag = 0.92;
|
||||
p.vx = random(-3, 3);
|
||||
p.vy = random(-3, 3);
|
||||
p.wander = 0.15;
|
||||
p.theta = random(0, 360) * Math.PI / 180;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
function effect1(particle) {
|
||||
particle.vy += PARTICLE_GRAVITY;
|
||||
particle.x += particle.vx;
|
||||
particle.y += particle.vy;
|
||||
|
||||
particle.alpha *= PARTICLE_ALPHA_FADEOUT;
|
||||
|
||||
ctx.fillStyle = 'rgba('+ particle.color[0] +','+ particle.color[1] +','+ particle.color[2] + ',' + particle.alpha + ')';
|
||||
ctx.fillRect(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, particle.size);
|
||||
}
|
||||
|
||||
// Effect based on Soulwire's demo: http://codepen.io/soulwire/pen/foktm
|
||||
function effect2(particle) {
|
||||
particle.x += particle.vx;
|
||||
particle.y += particle.vy;
|
||||
particle.vx *= particle.drag;
|
||||
particle.vy *= particle.drag;
|
||||
particle.theta += random( -0.5, 0.5 );
|
||||
particle.vx += Math.sin( particle.theta ) * 0.1;
|
||||
particle.vy += Math.cos( particle.theta ) * 0.1;
|
||||
particle.size *= 0.96;
|
||||
|
||||
ctx.fillStyle = 'rgba('+ particle.color[0] +','+ particle.color[1] +','+ particle.color[2] + ',' + particle.alpha + ')';
|
||||
ctx.beginPath();
|
||||
ctx.arc(Math.round(particle.x - 1), Math.round(particle.y - 1), particle.size, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
function drawParticles(timeDelta) {
|
||||
var particle;
|
||||
for (var i = particles.length; i--;) {
|
||||
particle = particles[i];
|
||||
if (!particle || particle.alpha < 0.01 || particle.size <= 0.5) { continue; }
|
||||
|
||||
if (effect === 1) { effect1(particle); }
|
||||
else if (effect === 2) { effect2(particle); }
|
||||
}
|
||||
}
|
||||
|
||||
function shake(editor, time) {
|
||||
cmNode = editor.getWrapperElement();
|
||||
shakeTime = shakeTimeMax = time;
|
||||
}
|
||||
|
||||
function random(min, max) {
|
||||
if (!max) { max = min; min = 0; }
|
||||
return min + ~~(Math.random() * (max - min + 1))
|
||||
}
|
||||
|
||||
function throttle (callback, limit) {
|
||||
var wait = false;
|
||||
return function () {
|
||||
if (!wait) {
|
||||
callback.apply(this, arguments);
|
||||
wait = true;
|
||||
setTimeout(function () {
|
||||
wait = false;
|
||||
}, limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loop() {
|
||||
if (!isActive) { return; }
|
||||
|
||||
ctx.clearRect(0, 0, w, h);
|
||||
|
||||
// get the time past the previous frame
|
||||
current_time = new Date().getTime();
|
||||
if(!lastTime) lastTime = current_time;
|
||||
dt = (current_time - lastTime) / 1000;
|
||||
lastTime = current_time;
|
||||
|
||||
if (shakeTime > 0) {
|
||||
shakeTime -= dt;
|
||||
magnitude = (shakeTime / shakeTimeMax) * shakeIntensity;
|
||||
shakeX = random(-magnitude, magnitude);
|
||||
shakeY = random(-magnitude, magnitude);
|
||||
cmNode.style.transform = 'translate(' + shakeX + 'px,' + shakeY + 'px)';
|
||||
}
|
||||
drawParticles();
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
|
||||
function onCodeMirrorChange(editor, change) {
|
||||
if (change.origin !== '+input' && change.origin !== '+delete') { return; }
|
||||
|
||||
if (editor.getOption('blastCode') === true || editor.getOption('blastCode').shake === undefined) {
|
||||
throttledShake(editor, 0.3);
|
||||
}
|
||||
throttledSpawnParticles(editor);
|
||||
}
|
||||
|
||||
|
||||
function init(editor) {
|
||||
isActive = true;
|
||||
|
||||
if (!canvas) {
|
||||
canvas = document.createElement('canvas');
|
||||
ctx = canvas.getContext('2d'),
|
||||
|
||||
canvas.id = 'code-blast-canvas'
|
||||
canvas.style.position = 'absolute';
|
||||
canvas.style.top = 0;
|
||||
canvas.style.left = 0;
|
||||
canvas.style.zIndex = 1;
|
||||
canvas.style.pointerEvents = 'none';
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
|
||||
document.body.appendChild(canvas);
|
||||
loop();
|
||||
}
|
||||
|
||||
editor.on("change", onCodeMirrorChange);
|
||||
}
|
||||
|
||||
function destroy(editor) {
|
||||
editor.off('change', onCodeMirrorChange);
|
||||
codemirrors.splice(codemirrors.indexOf(editor), 1);
|
||||
if (!codemirrors.length) {
|
||||
isActive = false;
|
||||
if (canvas) {
|
||||
canvas.remove();
|
||||
canvas = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CodeMirror.defineOption('blastCode', false, function(editor, val, old) {
|
||||
if (val) {
|
||||
codemirrors.push(editor);
|
||||
effect = val.effect || 2;
|
||||
init(editor);
|
||||
} else {
|
||||
destroy(editor);
|
||||
}
|
||||
|
||||
});
|
||||
})();
|
5117
src/lib/codemirror/keymap/vim.js
vendored
Normal file
5117
src/lib/codemirror/keymap/vim.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode('jade', function (config) {
|
||||
CodeMirror.defineMode("pug", function (config) {
|
||||
// token types
|
||||
var KEYWORD = 'keyword';
|
||||
var DOCTYPE = 'meta';
|
||||
@ -36,7 +36,7 @@ CodeMirror.defineMode('jade', function (config) {
|
||||
this.isInterpolating = false;
|
||||
this.interpolationNesting = 0;
|
||||
|
||||
this.jsState = jsMode.startState();
|
||||
this.jsState = CodeMirror.startState(jsMode);
|
||||
|
||||
this.restOfLine = '';
|
||||
|
||||
@ -386,7 +386,7 @@ CodeMirror.defineMode('jade', function (config) {
|
||||
if (state.inAttributeName && stream.match(/^[^=,\)!]+/)) {
|
||||
if (stream.peek() === '=' || stream.peek() === '!') {
|
||||
state.inAttributeName = false;
|
||||
state.jsState = jsMode.startState();
|
||||
state.jsState = CodeMirror.startState(jsMode);
|
||||
if (state.lastTag === 'script' && stream.current().trim().toLowerCase() === 'type') {
|
||||
state.attributeIsType = true;
|
||||
} else {
|
||||
@ -492,7 +492,7 @@ CodeMirror.defineMode('jade', function (config) {
|
||||
if (stream.indentation() > state.indentOf || (state.innerModeForLine && !stream.sol()) || force) {
|
||||
if (state.innerMode) {
|
||||
if (!state.innerState) {
|
||||
state.innerState = state.innerMode.startState ? state.innerMode.startState(stream.indentation()) : {};
|
||||
state.innerState = state.innerMode.startState ? CodeMirror.startState(state.innerMode, stream.indentation()) : {};
|
||||
}
|
||||
return stream.hideFirstChars(state.indentOf + 2, function () {
|
||||
return state.innerMode.token(stream, state.innerState) || true;
|
||||
@ -585,6 +585,7 @@ CodeMirror.defineMode('jade', function (config) {
|
||||
};
|
||||
}, 'javascript', 'css', 'htmlmixed');
|
||||
|
||||
CodeMirror.defineMIME('text/x-jade', 'jade');
|
||||
CodeMirror.defineMIME('text/x-pug', 'pug');
|
||||
CodeMirror.defineMIME('text/x-jade', 'pug');
|
||||
|
||||
});
|
7
src/lib/codemirror/theme/dracula.css
vendored
7
src/lib/codemirror/theme/dracula.css
vendored
@ -16,7 +16,7 @@
|
||||
.cm-s-dracula .CodeMirror-gutters { color: #282a36; }
|
||||
.cm-s-dracula .CodeMirror-cursor { border-left: solid thin #f8f8f0; }
|
||||
.cm-s-dracula .CodeMirror-linenumber { color: #6D8A88; }
|
||||
.cm-s-dracula.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }
|
||||
.cm-s-dracula .CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }
|
||||
.cm-s-dracula .CodeMirror-line::selection, .cm-s-dracula .CodeMirror-line > span::selection, .cm-s-dracula .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }
|
||||
.cm-s-dracula .CodeMirror-line::-moz-selection, .cm-s-dracula .CodeMirror-line > span::-moz-selection, .cm-s-dracula .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }
|
||||
.cm-s-dracula span.cm-comment { color: #6272a4; }
|
||||
@ -24,8 +24,7 @@
|
||||
.cm-s-dracula span.cm-number { color: #bd93f9; }
|
||||
.cm-s-dracula span.cm-variable { color: #50fa7b; }
|
||||
.cm-s-dracula span.cm-variable-2 { color: white; }
|
||||
.cm-s-dracula span.cm-def { color: #ffb86c; }
|
||||
.cm-s-dracula span.cm-keyword { color: #ff79c6; }
|
||||
.cm-s-dracula span.cm-def { color: #50fa7b; }
|
||||
.cm-s-dracula span.cm-operator { color: #ff79c6; }
|
||||
.cm-s-dracula span.cm-keyword { color: #ff79c6; }
|
||||
.cm-s-dracula span.cm-atom { color: #bd93f9; }
|
||||
@ -35,7 +34,7 @@
|
||||
.cm-s-dracula span.cm-qualifier { color: #50fa7b; }
|
||||
.cm-s-dracula span.cm-property { color: #66d9ef; }
|
||||
.cm-s-dracula span.cm-builtin { color: #50fa7b; }
|
||||
.cm-s-dracula span.cm-variable-3 { color: #50fa7b; }
|
||||
.cm-s-dracula span.cm-variable-3 { color: #ffb86c; }
|
||||
|
||||
.cm-s-dracula .CodeMirror-activeline-background { background: rgba(255,255,255,0.1); }
|
||||
.cm-s-dracula .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
|
||||
|
35
src/lib/codemirror/theme/duotone-dark.css
vendored
Normal file
35
src/lib/codemirror/theme/duotone-dark.css
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Name: DuoTone-Dark
|
||||
Author: by Bram de Haan, adapted from DuoTone themes by Simurai (http://simurai.com/projects/2016/01/01/duotone-themes)
|
||||
|
||||
CodeMirror template by Jan T. Sott (https://github.com/idleberg), adapted by Bram de Haan (https://github.com/atelierbram/)
|
||||
*/
|
||||
|
||||
.cm-s-duotone-dark.CodeMirror { background: #2a2734; color: #6c6783; }
|
||||
.cm-s-duotone-dark div.CodeMirror-selected { background: #545167!important; }
|
||||
.cm-s-duotone-dark .CodeMirror-gutters { background: #2a2734; border-right: 0px; }
|
||||
.cm-s-duotone-dark .CodeMirror-linenumber { color: #545167; }
|
||||
|
||||
/* begin cursor */
|
||||
.cm-s-duotone-dark .CodeMirror-cursor { border-left: 1px solid #ffad5c; /* border-left: 1px solid #ffad5c80; */ border-right: .5em solid #ffad5c; /* border-right: .5em solid #ffad5c80; */ opacity: .5; }
|
||||
.cm-s-duotone-dark .CodeMirror-activeline-background { background: #363342; /* background: #36334280; */ opacity: .5;}
|
||||
.cm-s-duotone-dark .cm-fat-cursor .CodeMirror-cursor { background: #ffad5c; /* background: #ffad5c80; */ opacity: .5;}
|
||||
/* end cursor */
|
||||
|
||||
.cm-s-duotone-dark span.cm-atom, .cm-s-duotone-dark span.cm-number, .cm-s-duotone-dark span.cm-keyword, .cm-s-duotone-dark span.cm-variable, .cm-s-duotone-dark span.cm-attribute, .cm-s-duotone-dark span.cm-quote, .cm-s-duotone-dark span.cm-hr, .cm-s-duotone-dark span.cm-link { color: #ffcc99; }
|
||||
|
||||
.cm-s-duotone-dark span.cm-property { color: #9a86fd; }
|
||||
.cm-s-duotone-dark span.cm-punctuation, .cm-s-duotone-dark span.cm-unit, .cm-s-duotone-dark span.cm-negative { color: #e09142; }
|
||||
.cm-s-duotone-dark span.cm-string { color: #ffb870; }
|
||||
.cm-s-duotone-dark span.cm-operator { color: #ffad5c; }
|
||||
.cm-s-duotone-dark span.cm-positive { color: #6a51e6; }
|
||||
|
||||
.cm-s-duotone-dark span.cm-variable-2, .cm-s-duotone-dark span.cm-variable-3, .cm-s-duotone-dark span.cm-string-2, .cm-s-duotone-dark span.cm-url { color: #7a63ee; }
|
||||
.cm-s-duotone-dark span.cm-def, .cm-s-duotone-dark span.cm-tag, .cm-s-duotone-dark span.cm-builtin, .cm-s-duotone-dark span.cm-qualifier, .cm-s-duotone-dark span.cm-header, .cm-s-duotone-dark span.cm-em { color: #eeebff; }
|
||||
.cm-s-duotone-dark span.cm-bracket, .cm-s-duotone-dark span.cm-comment { color: #6c6783; }
|
||||
|
||||
/* using #f00 red for errors, don't think any of the colorscheme variables will stand out enough, ... maybe by giving it a background-color ... */
|
||||
.cm-s-duotone-dark span.cm-error, .cm-s-duotone-dark span.cm-invalidchar { color: #f00; }
|
||||
|
||||
.cm-s-duotone-dark span.cm-header { font-weight: normal; }
|
||||
.cm-s-duotone-dark .CodeMirror-matchingbracket { text-decoration: underline; color: #eeebff !important; }
|
36
src/lib/codemirror/theme/duotone-light.css
vendored
Normal file
36
src/lib/codemirror/theme/duotone-light.css
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Name: DuoTone-Light
|
||||
Author: by Bram de Haan, adapted from DuoTone themes by Simurai (http://simurai.com/projects/2016/01/01/duotone-themes)
|
||||
|
||||
CodeMirror template by Jan T. Sott (https://github.com/idleberg), adapted by Bram de Haan (https://github.com/atelierbram/)
|
||||
*/
|
||||
|
||||
.cm-s-duotone-light.CodeMirror { background: #faf8f5; color: #b29762; }
|
||||
.cm-s-duotone-light div.CodeMirror-selected { background: #e3dcce !important; }
|
||||
.cm-s-duotone-light .CodeMirror-gutters { background: #faf8f5; border-right: 0px; }
|
||||
.cm-s-duotone-light .CodeMirror-linenumber { color: #cdc4b1; }
|
||||
|
||||
/* begin cursor */
|
||||
.cm-s-duotone-light .CodeMirror-cursor { border-left: 1px solid #93abdc; /* border-left: 1px solid #93abdc80; */ border-right: .5em solid #93abdc; /* border-right: .5em solid #93abdc80; */ opacity: .5; }
|
||||
.cm-s-duotone-light .CodeMirror-activeline-background { background: #e3dcce; /* background: #e3dcce80; */ opacity: .5; }
|
||||
.cm-s-duotone-light .cm-fat-cursor .CodeMirror-cursor { background: #93abdc; /* #93abdc80; */ opacity: .5; }
|
||||
/* end cursor */
|
||||
|
||||
.cm-s-duotone-light span.cm-atom, .cm-s-duotone-light span.cm-number, .cm-s-duotone-light span.cm-keyword, .cm-s-duotone-light span.cm-variable, .cm-s-duotone-light span.cm-attribute, .cm-s-duotone-light span.cm-quote, .cm-s-duotone-light-light span.cm-hr, .cm-s-duotone-light-light span.cm-link { color: #063289; }
|
||||
|
||||
.cm-s-duotone-light span.cm-property { color: #b29762; }
|
||||
.cm-s-duotone-light span.cm-punctuation, .cm-s-duotone-light span.cm-unit, .cm-s-duotone-light span.cm-negative { color: #063289; }
|
||||
.cm-s-duotone-light span.cm-string, .cm-s-duotone-light span.cm-operator { color: #1659df; }
|
||||
.cm-s-duotone-light span.cm-positive { color: #896724; }
|
||||
|
||||
.cm-s-duotone-light span.cm-variable-2, .cm-s-duotone-light span.cm-variable-3, .cm-s-duotone-light span.cm-string-2, .cm-s-duotone-light span.cm-url { color: #896724; }
|
||||
.cm-s-duotone-light span.cm-def, .cm-s-duotone-light span.cm-tag, .cm-s-duotone-light span.cm-builtin, .cm-s-duotone-light span.cm-qualifier, .cm-s-duotone-light span.cm-header, .cm-s-duotone-light span.cm-em { color: #2d2006; }
|
||||
.cm-s-duotone-light span.cm-bracket, .cm-s-duotone-light span.cm-comment { color: #b6ad9a; }
|
||||
|
||||
/* using #f00 red for errors, don't think any of the colorscheme variables will stand out enough, ... maybe by giving it a background-color ... */
|
||||
/* .cm-s-duotone-light span.cm-error { background: #896724; color: #728fcb; } */
|
||||
.cm-s-duotone-light span.cm-error, .cm-s-duotone-light span.cm-invalidchar { color: #f00; }
|
||||
|
||||
.cm-s-duotone-light span.cm-header { font-weight: normal; }
|
||||
.cm-s-duotone-light .CodeMirror-matchingbracket { text-decoration: underline; color: #faf8f5 !important; }
|
||||
|
2
src/lib/codemirror/theme/material.css
vendored
2
src/lib/codemirror/theme/material.css
vendored
@ -7,7 +7,7 @@
|
||||
|
||||
*/
|
||||
|
||||
.cm-s-material {
|
||||
.cm-s-material.CodeMirror {
|
||||
background-color: #263238;
|
||||
color: rgba(233, 237, 237, 1);
|
||||
}
|
||||
|
85
src/lib/codemirror/theme/panda-syntax.css
vendored
Normal file
85
src/lib/codemirror/theme/panda-syntax.css
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Name: Panda Syntax
|
||||
Author: Siamak Mokhtari (http://github.com/siamak/)
|
||||
CodeMirror template by Siamak Mokhtari (https://github.com/siamak/atom-panda-syntax)
|
||||
*/
|
||||
.cm-s-panda-syntax {
|
||||
background: #292A2B;
|
||||
color: #E6E6E6;
|
||||
line-height: 1.5;
|
||||
font-family: 'Operator Mono', 'Source Sans Pro', Menlo, Monaco, Consolas, Courier New, monospace;
|
||||
}
|
||||
.cm-s-panda-syntax .CodeMirror-cursor { border-color: #ff2c6d; }
|
||||
.cm-s-panda-syntax .CodeMirror-activeline-background {
|
||||
background: rgba(99, 123, 156, 0.1);
|
||||
}
|
||||
.cm-s-panda-syntax .CodeMirror-selected {
|
||||
background: #FFF;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-comment {
|
||||
font-style: italic;
|
||||
color: #676B79;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-operator {
|
||||
color: #f3f3f3;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-string {
|
||||
color: #19F9D8;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-string-2 {
|
||||
color: #FFB86C;
|
||||
}
|
||||
|
||||
.cm-s-panda-syntax .cm-tag {
|
||||
color: #ff2c6d;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-meta {
|
||||
color: #b084eb;
|
||||
}
|
||||
|
||||
.cm-s-panda-syntax .cm-number {
|
||||
color: #FFB86C;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-atom {
|
||||
color: #ff2c6d;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-keyword {
|
||||
color: #FF75B5;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-variable {
|
||||
color: #ffb86c;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-variable-2 {
|
||||
color: #ff9ac1;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-variable-3 {
|
||||
color: #ff9ac1;
|
||||
}
|
||||
|
||||
.cm-s-panda-syntax .cm-def {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-property {
|
||||
color: #f3f3f3;
|
||||
}
|
||||
.cm-s-panda-syntax .cm-unit {
|
||||
color: #ffb86c;
|
||||
}
|
||||
|
||||
.cm-s-panda-syntax .cm-attribute {
|
||||
color: #ffb86c;
|
||||
}
|
||||
|
||||
.cm-s-panda-syntax .CodeMirror-matchingbracket {
|
||||
border-bottom: 1px dotted #19F9D8;
|
||||
padding-bottom: 2px;
|
||||
color: #e6e6e6;
|
||||
}
|
||||
.cm-s-panda-syntax .CodeMirror-gutters {
|
||||
background: #292a2b;
|
||||
border-right-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.cm-s-panda-syntax .CodeMirror-linenumber {
|
||||
color: #e6e6e6;
|
||||
opacity: 0.6;
|
||||
}
|
1
src/lib/codemirror/theme/pastel-on-dark.css
vendored
1
src/lib/codemirror/theme/pastel-on-dark.css
vendored
@ -11,7 +11,6 @@
|
||||
background: #2c2827;
|
||||
color: #8F938F;
|
||||
line-height: 1.5;
|
||||
font-size: 14px;
|
||||
}
|
||||
.cm-s-pastel-on-dark div.CodeMirror-selected { background: rgba(221,240,255,0.2); }
|
||||
.cm-s-pastel-on-dark .CodeMirror-line::selection, .cm-s-pastel-on-dark .CodeMirror-line > span::selection, .cm-s-pastel-on-dark .CodeMirror-line > span > span::selection { background: rgba(221,240,255,0.2); }
|
||||
|
@ -4,7 +4,7 @@ http://ethanschoonover.com/solarized
|
||||
*/
|
||||
|
||||
/*
|
||||
Solarized color pallet
|
||||
Solarized color palette
|
||||
http://ethanschoonover.com/solarized/img/solarized-palette.png
|
||||
*/
|
||||
|
||||
@ -34,7 +34,7 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png
|
||||
}
|
||||
.cm-s-solarized.cm-s-dark {
|
||||
color: #839496;
|
||||
background-color: #002b36;
|
||||
background-color: #002b36;
|
||||
text-shadow: #002b36 0 1px;
|
||||
}
|
||||
.cm-s-solarized.cm-s-light {
|
||||
@ -113,32 +113,34 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png
|
||||
box-shadow: inset 7px 0 12px -6px #000;
|
||||
}
|
||||
|
||||
/* Gutter border and some shadow from it */
|
||||
/* Remove gutter border */
|
||||
.cm-s-solarized .CodeMirror-gutters {
|
||||
border-right: 1px solid;
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
/* Gutter colors and line number styling based of color scheme (dark / light) */
|
||||
|
||||
/* Dark */
|
||||
.cm-s-solarized.cm-s-dark .CodeMirror-gutters {
|
||||
background-color: #002b36;
|
||||
border-color: #00232c;
|
||||
background-color: #073642;
|
||||
}
|
||||
|
||||
.cm-s-solarized.cm-s-dark .CodeMirror-linenumber {
|
||||
color: #586e75;
|
||||
text-shadow: #021014 0 -1px;
|
||||
}
|
||||
|
||||
/* Light */
|
||||
.cm-s-solarized.cm-s-light .CodeMirror-gutters {
|
||||
background-color: #fdf6e3;
|
||||
border-color: #eee8d5;
|
||||
background-color: #eee8d5;
|
||||
}
|
||||
|
||||
.cm-s-solarized.cm-s-light .CodeMirror-linenumber {
|
||||
color: #839496;
|
||||
}
|
||||
|
||||
/* Common */
|
||||
.cm-s-solarized .CodeMirror-linenumber {
|
||||
color: #586e75;
|
||||
padding: 0 5px;
|
||||
}
|
||||
.cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; }
|
||||
@ -149,15 +151,19 @@ http://ethanschoonover.com/solarized/img/solarized-palette.png
|
||||
color: #586e75;
|
||||
}
|
||||
|
||||
/* Cursor */
|
||||
.cm-s-solarized .CodeMirror-cursor { border-left: 1px solid #819090; }
|
||||
|
||||
/*
|
||||
Active line. Negative margin compensates left padding of the text in the
|
||||
view-port
|
||||
*/
|
||||
/* Fat cursor */
|
||||
.cm-s-solarized.cm-s-light.cm-fat-cursor .CodeMirror-cursor { background: #77ee77; }
|
||||
.cm-s-solarized.cm-s-light .cm-animate-fat-cursor { background-color: #77ee77; }
|
||||
.cm-s-solarized.cm-s-dark.cm-fat-cursor .CodeMirror-cursor { background: #586e75; }
|
||||
.cm-s-solarized.cm-s-dark .cm-animate-fat-cursor { background-color: #586e75; }
|
||||
|
||||
/* Active line */
|
||||
.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background {
|
||||
background: rgba(255, 255, 255, 0.10);
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
.cm-s-solarized.cm-s-light .CodeMirror-activeline-background {
|
||||
background: rgba(0, 0, 0, 0.10);
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
}
|
169
src/lib/codemirror/theme/solarized light.css
vendored
Normal file
169
src/lib/codemirror/theme/solarized light.css
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
Solarized theme for code-mirror
|
||||
http://ethanschoonover.com/solarized
|
||||
*/
|
||||
|
||||
/*
|
||||
Solarized color palette
|
||||
http://ethanschoonover.com/solarized/img/solarized-palette.png
|
||||
*/
|
||||
|
||||
.solarized.base03 { color: #002b36; }
|
||||
.solarized.base02 { color: #073642; }
|
||||
.solarized.base01 { color: #586e75; }
|
||||
.solarized.base00 { color: #657b83; }
|
||||
.solarized.base0 { color: #839496; }
|
||||
.solarized.base1 { color: #93a1a1; }
|
||||
.solarized.base2 { color: #eee8d5; }
|
||||
.solarized.base3 { color: #fdf6e3; }
|
||||
.solarized.solar-yellow { color: #b58900; }
|
||||
.solarized.solar-orange { color: #cb4b16; }
|
||||
.solarized.solar-red { color: #dc322f; }
|
||||
.solarized.solar-magenta { color: #d33682; }
|
||||
.solarized.solar-violet { color: #6c71c4; }
|
||||
.solarized.solar-blue { color: #268bd2; }
|
||||
.solarized.solar-cyan { color: #2aa198; }
|
||||
.solarized.solar-green { color: #859900; }
|
||||
|
||||
/* Color scheme for code-mirror */
|
||||
|
||||
.cm-s-solarized {
|
||||
line-height: 1.45em;
|
||||
color-profile: sRGB;
|
||||
rendering-intent: auto;
|
||||
}
|
||||
.cm-s-solarized.cm-s-dark {
|
||||
color: #839496;
|
||||
background-color: #002b36;
|
||||
text-shadow: #002b36 0 1px;
|
||||
}
|
||||
.cm-s-solarized.cm-s-light {
|
||||
background-color: #fdf6e3;
|
||||
color: #657b83;
|
||||
text-shadow: #eee8d5 0 1px;
|
||||
}
|
||||
|
||||
.cm-s-solarized .CodeMirror-widget {
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.cm-s-solarized .cm-header { color: #586e75; }
|
||||
.cm-s-solarized .cm-quote { color: #93a1a1; }
|
||||
|
||||
.cm-s-solarized .cm-keyword { color: #cb4b16; }
|
||||
.cm-s-solarized .cm-atom { color: #d33682; }
|
||||
.cm-s-solarized .cm-number { color: #d33682; }
|
||||
.cm-s-solarized .cm-def { color: #2aa198; }
|
||||
|
||||
.cm-s-solarized .cm-variable { color: #839496; }
|
||||
.cm-s-solarized .cm-variable-2 { color: #b58900; }
|
||||
.cm-s-solarized .cm-variable-3 { color: #6c71c4; }
|
||||
|
||||
.cm-s-solarized .cm-property { color: #2aa198; }
|
||||
.cm-s-solarized .cm-operator { color: #6c71c4; }
|
||||
|
||||
.cm-s-solarized .cm-comment { color: #586e75; font-style:italic; }
|
||||
|
||||
.cm-s-solarized .cm-string { color: #859900; }
|
||||
.cm-s-solarized .cm-string-2 { color: #b58900; }
|
||||
|
||||
.cm-s-solarized .cm-meta { color: #859900; }
|
||||
.cm-s-solarized .cm-qualifier { color: #b58900; }
|
||||
.cm-s-solarized .cm-builtin { color: #d33682; }
|
||||
.cm-s-solarized .cm-bracket { color: #cb4b16; }
|
||||
.cm-s-solarized .CodeMirror-matchingbracket { color: #859900; }
|
||||
.cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; }
|
||||
.cm-s-solarized .cm-tag { color: #93a1a1; }
|
||||
.cm-s-solarized .cm-attribute { color: #2aa198; }
|
||||
.cm-s-solarized .cm-hr {
|
||||
color: transparent;
|
||||
border-top: 1px solid #586e75;
|
||||
display: block;
|
||||
}
|
||||
.cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; }
|
||||
.cm-s-solarized .cm-special { color: #6c71c4; }
|
||||
.cm-s-solarized .cm-em {
|
||||
color: #999;
|
||||
text-decoration: underline;
|
||||
text-decoration-style: dotted;
|
||||
}
|
||||
.cm-s-solarized .cm-strong { color: #eee; }
|
||||
.cm-s-solarized .cm-error,
|
||||
.cm-s-solarized .cm-invalidchar {
|
||||
color: #586e75;
|
||||
border-bottom: 1px dotted #dc322f;
|
||||
}
|
||||
|
||||
.cm-s-solarized.cm-s-dark div.CodeMirror-selected { background: #073642; }
|
||||
.cm-s-solarized.cm-s-dark.CodeMirror ::selection { background: rgba(7, 54, 66, 0.99); }
|
||||
.cm-s-solarized.cm-s-dark .CodeMirror-line::-moz-selection, .cm-s-dark .CodeMirror-line > span::-moz-selection, .cm-s-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(7, 54, 66, 0.99); }
|
||||
|
||||
.cm-s-solarized.cm-s-light div.CodeMirror-selected { background: #eee8d5; }
|
||||
.cm-s-solarized.cm-s-light .CodeMirror-line::selection, .cm-s-light .CodeMirror-line > span::selection, .cm-s-light .CodeMirror-line > span > span::selection { background: #eee8d5; }
|
||||
.cm-s-solarized.cm-s-light .CodeMirror-line::-moz-selection, .cm-s-ligh .CodeMirror-line > span::-moz-selection, .cm-s-ligh .CodeMirror-line > span > span::-moz-selection { background: #eee8d5; }
|
||||
|
||||
/* Editor styling */
|
||||
|
||||
|
||||
|
||||
/* Little shadow on the view-port of the buffer view */
|
||||
.cm-s-solarized.CodeMirror {
|
||||
-moz-box-shadow: inset 7px 0 12px -6px #000;
|
||||
-webkit-box-shadow: inset 7px 0 12px -6px #000;
|
||||
box-shadow: inset 7px 0 12px -6px #000;
|
||||
}
|
||||
|
||||
/* Remove gutter border */
|
||||
.cm-s-solarized .CodeMirror-gutters {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
/* Gutter colors and line number styling based of color scheme (dark / light) */
|
||||
|
||||
/* Dark */
|
||||
.cm-s-solarized.cm-s-dark .CodeMirror-gutters {
|
||||
background-color: #073642;
|
||||
}
|
||||
|
||||
.cm-s-solarized.cm-s-dark .CodeMirror-linenumber {
|
||||
color: #586e75;
|
||||
text-shadow: #021014 0 -1px;
|
||||
}
|
||||
|
||||
/* Light */
|
||||
.cm-s-solarized.cm-s-light .CodeMirror-gutters {
|
||||
background-color: #eee8d5;
|
||||
}
|
||||
|
||||
.cm-s-solarized.cm-s-light .CodeMirror-linenumber {
|
||||
color: #839496;
|
||||
}
|
||||
|
||||
/* Common */
|
||||
.cm-s-solarized .CodeMirror-linenumber {
|
||||
padding: 0 5px;
|
||||
}
|
||||
.cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; }
|
||||
.cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; }
|
||||
.cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; }
|
||||
|
||||
.cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text {
|
||||
color: #586e75;
|
||||
}
|
||||
|
||||
/* Cursor */
|
||||
.cm-s-solarized .CodeMirror-cursor { border-left: 1px solid #819090; }
|
||||
|
||||
/* Fat cursor */
|
||||
.cm-s-solarized.cm-s-light.cm-fat-cursor .CodeMirror-cursor { background: #77ee77; }
|
||||
.cm-s-solarized.cm-s-light .cm-animate-fat-cursor { background-color: #77ee77; }
|
||||
.cm-s-solarized.cm-s-dark.cm-fat-cursor .CodeMirror-cursor { background: #586e75; }
|
||||
.cm-s-solarized.cm-s-dark .cm-animate-fat-cursor { background-color: #586e75; }
|
||||
|
||||
/* Active line */
|
||||
.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background {
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
.cm-s-solarized.cm-s-light .CodeMirror-activeline-background {
|
||||
background: rgba(0, 0, 0, 0.06);
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
"<all_urls>",
|
||||
"downloads"
|
||||
],
|
||||
"content_security_policy": "script-src 'self' https://ajax.googleapis.com https://code.jquery.com https://cdnjs.cloudflare.com https://unpkg.com https://maxcdn.bootstrapcdn.com https://cdn.jsdelivr.net/ https://www.google-analytics.com 'unsafe-eval'; object-src 'self'",
|
||||
"content_security_policy": "script-src 'self' filesystem: http://localhost:* https://localhost:* https://ajax.googleapis.com https://code.jquery.com https://cdnjs.cloudflare.com https://unpkg.com https://maxcdn.com https://cdn77.com https://maxcdn.bootstrapcdn.com https://cdn.jsdelivr.net/ https://www.google-analytics.com 'unsafe-eval'; object-src 'self'",
|
||||
"options_ui": {
|
||||
"page": "options.html",
|
||||
"chrome_style": true
|
||||
|
492
src/script.js
492
src/script.js
@ -2,9 +2,9 @@
|
||||
/* global layoutBtn1, layoutBtn2, layoutBtn3, helpModal, notificationsModal, addLibraryModal,
|
||||
onboardModal, layoutBtn1, layoutBtn2, layoutBtn3, layoutBtn4, helpBtn, onboardModal, onboardModal,
|
||||
addLibraryModal, addLibraryModal, notificationsBtn, notificationsModal, notificationsModal,
|
||||
notificationsModal, notificationsBtn, codepenBtn, saveHtmlBtn, openBtn, saveBtn, newBtn,
|
||||
settingsBtn, onboardModal, notificationsBtn, onboardShowInTabOptionBtn, onboardDontShowInTabOptionBtn
|
||||
TextareaAutoComplete */
|
||||
notificationsModal, notificationsBtn, codepenBtn, saveHtmlBtn, saveBtn, settingsBtn,
|
||||
onboardModal, settingsModal, notificationsBtn, onboardShowInTabOptionBtn, editorThemeLinkTag,
|
||||
onboardDontShowInTabOptionBtn, TextareaAutoComplete, savedItemCountEl */
|
||||
/* eslint-disable no-extra-semi */
|
||||
;(function (alertsService) {
|
||||
|
||||
@ -37,7 +37,7 @@ TextareaAutoComplete */
|
||||
var modes = {};
|
||||
modes[HtmlModes.HTML] = { label: 'HTML', cmMode: 'htmlmixed', codepenVal: 'none' };
|
||||
modes[HtmlModes.MARKDOWN] = { label: 'Markdown', cmMode: 'markdown', codepenVal: 'markdown' };
|
||||
modes[HtmlModes.JADE] = { label: 'Jade', cmMode: 'jade', codepenVal: 'jade' };
|
||||
modes[HtmlModes.JADE] = { label: 'Pug', cmMode: 'pug', codepenVal: 'pug' };
|
||||
modes[JsModes.JS] = { label: 'JS', cmMode: 'javascript', codepenVal: 'none' };
|
||||
modes[JsModes.COFFEESCRIPT] = { label: 'CoffeeScript', cmMode: 'coffeescript', codepenVal: 'coffeescript' };
|
||||
modes[JsModes.ES6] = { label: 'ES6 (Babel)', cmMode: 'jsx', codepenVal: 'babel' };
|
||||
@ -50,6 +50,7 @@ TextareaAutoComplete */
|
||||
|
||||
var updateTimer
|
||||
, updateDelay = 500
|
||||
, unsavedEditWarningCount = 15
|
||||
, currentLayoutMode
|
||||
, hasSeenNotifications = true
|
||||
, htmlMode = HtmlModes.HTML
|
||||
@ -57,11 +58,11 @@ TextareaAutoComplete */
|
||||
, cssMode = CssModes.CSS
|
||||
, sass
|
||||
, currentItem
|
||||
, unsavedEditCount
|
||||
, savedItems
|
||||
, minCodeWrapSize = 33
|
||||
, mainSplitInstance
|
||||
, codeSplitInstance
|
||||
// TODO: for legacy reasons when. Will be refactored as global preferences.
|
||||
, prefs = {}
|
||||
, codeInPreview = { html: null, css: null, js: null }
|
||||
, isSavedItemsPaneOpen = false
|
||||
@ -149,7 +150,6 @@ TextareaAutoComplete */
|
||||
} else {
|
||||
options.sizes = [ 33.33, 33.33, 33.33 ];
|
||||
}
|
||||
utils.log('reset splitting', currentItem);
|
||||
|
||||
codeSplitInstance = Split(['#js-html-code', '#js-css-code', '#js-js-code'], options);
|
||||
mainSplitInstance = Split(['#js-code-side', '#js-demo-side' ], {
|
||||
@ -294,6 +294,8 @@ TextareaAutoComplete */
|
||||
utils.log('saving key', key || currentItem.id, currentItem)
|
||||
saveSetting(key || currentItem.id, currentItem, function () {
|
||||
alertsService.add('Item saved.');
|
||||
unsavedEditCount = 0;
|
||||
saveBtn.classList.remove('is-marked');
|
||||
});
|
||||
}
|
||||
|
||||
@ -309,8 +311,11 @@ TextareaAutoComplete */
|
||||
+ '<a class="js-saved-item-tile__close-btn saved-item-tile__close-btn hint--left" aria-label="Remove">X</a>'
|
||||
+ '<h3 class="saved-item-tile__title">' + item.title + '</h3><span class="saved-item-tile__meta">Last updated: ' + utils.getHumanDate(item.updatedOn) + '</span></div>';
|
||||
});
|
||||
savedItemCountEl.textContent = '(' + items.length + ')';
|
||||
savedItemCountEl.style.display = 'inline';
|
||||
} else {
|
||||
html += '<h2 class="opacity--30">Nothing saved here.</h2>';
|
||||
savedItemCountEl.style.display = 'none';
|
||||
}
|
||||
savedItemsPane.querySelector('#js-saved-items-wrap').innerHTML = html;
|
||||
toggleSavedItemsPane();
|
||||
@ -327,13 +332,19 @@ TextareaAutoComplete */
|
||||
isSavedItemsPaneOpen = savedItemsPane.classList.contains('is-open');
|
||||
document.body.classList[isSavedItemsPaneOpen ? 'add' : 'remove']('overlay-visible');
|
||||
}
|
||||
function openSavedItemsPane() {
|
||||
|
||||
/**
|
||||
* Fetches all items from storage
|
||||
* @param {boolean} shouldSaveGlobally Whether to store the fetched items in global arr for later use.
|
||||
* @return {promise} Promise.
|
||||
*/
|
||||
function fetchItems(shouldSaveGlobally) {
|
||||
var d = deferred();
|
||||
chrome.storage.local.get('items', function (result) {
|
||||
var itemIds = Object.getOwnPropertyNames(result.items || {}),
|
||||
items = [];
|
||||
if (!itemIds.length) {
|
||||
populateItemsInSavedPane([]);
|
||||
return;
|
||||
d.resolve([]);
|
||||
}
|
||||
|
||||
savedItems = savedItems || [];
|
||||
@ -342,35 +353,48 @@ TextareaAutoComplete */
|
||||
|
||||
/* eslint-disable no-loop-func */
|
||||
chrome.storage.local.get(itemIds[i], function (itemResult) {
|
||||
savedItems[itemIds[i]] = itemResult[itemIds[i]];
|
||||
if (shouldSaveGlobally) {
|
||||
savedItems[itemIds[i]] = itemResult[itemIds[i]];
|
||||
}
|
||||
items.push(itemResult[itemIds[i]]);
|
||||
// Check if we have all items now.
|
||||
if (itemIds.length === items.length) {
|
||||
populateItemsInSavedPane(items);
|
||||
d.resolve(items)
|
||||
}
|
||||
});
|
||||
|
||||
/* eslint-enable no-loop-func */
|
||||
}
|
||||
});
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
function openSavedItemsPane() {
|
||||
fetchItems(true).then(function (items) {
|
||||
populateItemsInSavedPane(items);
|
||||
});
|
||||
}
|
||||
function setCurrentItem(item) {
|
||||
currentItem = item;
|
||||
// Reset unsaved count, in UI also.
|
||||
unsavedEditCount = 0;
|
||||
saveBtn.classList.remove('is-marked');
|
||||
}
|
||||
function createNewItem() {
|
||||
var d = new Date();
|
||||
currentItem = {
|
||||
setCurrentItem({
|
||||
title: 'Untitled ' + d.getDate() + '-' + (d.getMonth() + 1) + '-' + d.getHours() + ':' + d.getMinutes(),
|
||||
html: '',
|
||||
css: '',
|
||||
js: '',
|
||||
externalLibs: { js: '', css: '' },
|
||||
layoutMode: currentLayoutMode
|
||||
};
|
||||
alertsService.add('New item created');
|
||||
});
|
||||
refreshEditor();
|
||||
alertsService.add('New item created');
|
||||
}
|
||||
function openItem(itemId) {
|
||||
currentItem = savedItems[itemId];
|
||||
// codeSplitInstance.setSizes([ 33.3, 33.3, 33.3 ]);
|
||||
setCurrentItem(savedItems[itemId]);
|
||||
refreshEditor();
|
||||
alertsService.add('Saved item loaded');
|
||||
}
|
||||
@ -398,6 +422,9 @@ TextareaAutoComplete */
|
||||
createNewItem();
|
||||
}
|
||||
});
|
||||
// Remove from cached list
|
||||
delete savedItems[itemId];
|
||||
|
||||
trackEvent('fn', 'itemRemoved');
|
||||
}
|
||||
|
||||
@ -405,7 +432,13 @@ TextareaAutoComplete */
|
||||
titleInput.value = currentItem.title || 'Untitled';
|
||||
externalJsTextarea.value = (currentItem.externalLibs && currentItem.externalLibs.js) || '';
|
||||
externalCssTextarea.value = (currentItem.externalLibs && currentItem.externalLibs.css) || '';
|
||||
externalJsTextarea.dispatchEvent(new Event('change'));
|
||||
|
||||
utils.log('refresh editor')
|
||||
// Set the modes manually here, so that the preview refresh triggered by the `setValue`
|
||||
// statements below, operate on correct modes.
|
||||
htmlMode = currentItem.htmlMode || prefs.htmlMode || HtmlModes.HTML;
|
||||
cssMode = currentItem.cssMode || prefs.cssMode || CssModes.CSS;
|
||||
jsMode = currentItem.jsMode || prefs.jsMode || JsModes.JS;
|
||||
|
||||
scope.cm.html.setValue(currentItem.html);
|
||||
scope.cm.css.setValue(currentItem.css);
|
||||
@ -414,9 +447,16 @@ TextareaAutoComplete */
|
||||
scope.cm.css.refresh();
|
||||
scope.cm.js.refresh();
|
||||
|
||||
updateHtmlMode(currentItem.htmlMode || prefs.htmlMode || HtmlModes.HTML);
|
||||
updateJsMode(currentItem.jsMode || prefs.jsMode || JsModes.JS);
|
||||
updateCssMode(currentItem.cssMode || prefs.cssMode || CssModes.CSS);
|
||||
// To have the library count updated
|
||||
updateExternalLibUi();
|
||||
|
||||
// Set preview only when all modes are updated so that preview doesn't generate on partially
|
||||
// correct modes and also doesn't happen 3 times.
|
||||
Promise.all([
|
||||
updateHtmlMode(htmlMode),
|
||||
updateCssMode(cssMode),
|
||||
updateJsMode(jsMode)
|
||||
]).then(() => scope.setPreviewContent(true));
|
||||
|
||||
toggleLayout(currentItem.layoutMode || prefs.layoutMode);
|
||||
}
|
||||
@ -426,6 +466,7 @@ TextareaAutoComplete */
|
||||
notificationsModal.classList.remove('is-modal-visible');
|
||||
addLibraryModal.classList.remove('is-modal-visible');
|
||||
onboardModal.classList.remove('is-modal-visible');
|
||||
settingsModal.classList.remove('is-modal-visible');
|
||||
toggleSavedItemsPane(false);
|
||||
document.dispatchEvent(new Event('overlaysClosed'));
|
||||
}
|
||||
@ -435,10 +476,15 @@ TextareaAutoComplete */
|
||||
*/
|
||||
function handleModeRequirements(mode) {
|
||||
// Exit if already loaded
|
||||
if (modes[mode].hasLoaded) { return; }
|
||||
var d = deferred();
|
||||
if (modes[mode].hasLoaded) {
|
||||
d.resolve();
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
function setLoadedFlag() {
|
||||
modes[mode].hasLoaded = true;
|
||||
d.resolve();
|
||||
}
|
||||
|
||||
if (mode === HtmlModes.JADE) {
|
||||
@ -460,35 +506,33 @@ TextareaAutoComplete */
|
||||
loadJS('lib/babel.min.js').then(setLoadedFlag);
|
||||
} else if (mode === JsModes.TS) {
|
||||
loadJS('lib/typescript.js').then(setLoadedFlag);
|
||||
} else {
|
||||
d.resolve();
|
||||
}
|
||||
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
function updateHtmlMode(value) {
|
||||
htmlMode = value;
|
||||
htmlModelLabel.textContent = modes[value].label;
|
||||
handleModeRequirements(value);
|
||||
scope.cm.html.setOption('mode', modes[value].cmMode);
|
||||
CodeMirror.autoLoadMode(scope.cm.html, modes[value].cmPath || modes[value].cmMode);
|
||||
return handleModeRequirements(value);
|
||||
}
|
||||
function updateCssMode(value) {
|
||||
cssMode = value;
|
||||
cssModelLabel.textContent = modes[value].label;
|
||||
handleModeRequirements(value);
|
||||
scope.cm.css.setOption('mode', modes[value].cmMode);
|
||||
CodeMirror.autoLoadMode(scope.cm.css, modes[value].cmPath || modes[value].cmMode);
|
||||
return handleModeRequirements(value);
|
||||
}
|
||||
function updateJsMode(value) {
|
||||
jsMode = value;
|
||||
jsModelLabel.textContent = modes[value].label;
|
||||
handleModeRequirements(value);
|
||||
scope.cm.js.setOption('mode', modes[value].cmMode);
|
||||
CodeMirror.autoLoadMode(scope.cm.js, modes[value].cmPath || modes[value].cmMode);
|
||||
// FIXME: Will be saved as part of scope settings
|
||||
/*
|
||||
chrome.storage.sync.set({
|
||||
jsMode: value
|
||||
}, function () {});
|
||||
*/
|
||||
return handleModeRequirements(value);
|
||||
}
|
||||
|
||||
// computeHtml, computeCss & computeJs evaluate the final code according
|
||||
@ -499,9 +543,9 @@ TextareaAutoComplete */
|
||||
if (htmlMode === HtmlModes.HTML) {
|
||||
d.resolve(code);
|
||||
} else if (htmlMode === HtmlModes.MARKDOWN) {
|
||||
d.resolve(marked(code));
|
||||
d.resolve(marked ? marked(code) : code);
|
||||
} else if (htmlMode === HtmlModes.JADE) {
|
||||
d.resolve(jade.render(code));
|
||||
d.resolve(window.jade ? jade.render(code) : code);
|
||||
}
|
||||
|
||||
return d.promise;
|
||||
@ -514,13 +558,17 @@ TextareaAutoComplete */
|
||||
if (cssMode === CssModes.CSS) {
|
||||
d.resolve(code);
|
||||
} else if (cssMode === CssModes.SCSS || cssMode === CssModes.SASS) {
|
||||
sass.compile(code, { indentedSyntax: cssMode === CssModes.SASS }, function(result) {
|
||||
// Something was wrong
|
||||
if (result.line && result.message) {
|
||||
showErrors('css', [ { lineNumber: result.line - 1, message: result.message } ]);
|
||||
}
|
||||
d.resolve(result.text);
|
||||
});
|
||||
if (sass && code) {
|
||||
sass.compile(code, { indentedSyntax: cssMode === CssModes.SASS }, function(result) {
|
||||
// Something was wrong
|
||||
if (result.line && result.message) {
|
||||
showErrors('css', [ { lineNumber: result.line - 1, message: result.message } ]);
|
||||
}
|
||||
d.resolve(result.text);
|
||||
});
|
||||
} else {
|
||||
d.resolve(code);
|
||||
}
|
||||
} else if (cssMode === CssModes.LESS) {
|
||||
less.render(code).then(function (result) {
|
||||
d.resolve(result.css);
|
||||
@ -547,6 +595,10 @@ TextareaAutoComplete */
|
||||
var code = scope.cm.js.getValue();
|
||||
|
||||
cleanupErrors('js');
|
||||
if (!code) {
|
||||
d.resolve('');
|
||||
return d.promise;
|
||||
}
|
||||
var ast;
|
||||
|
||||
if (jsMode === JsModes.JS) {
|
||||
@ -564,6 +616,10 @@ TextareaAutoComplete */
|
||||
}
|
||||
} else if (jsMode === JsModes.COFFEESCRIPT) {
|
||||
var coffeeCode;
|
||||
if (!window.CoffeeScript) {
|
||||
d.resolve('');
|
||||
return d.promise;
|
||||
}
|
||||
try {
|
||||
coffeeCode = CoffeeScript.compile(code, { bare: true });
|
||||
} catch (e) {
|
||||
@ -578,6 +634,10 @@ TextareaAutoComplete */
|
||||
d.resolve(escodegen.generate(ast));
|
||||
}
|
||||
} else if (jsMode === JsModes.ES6) {
|
||||
if (!window.Babel) {
|
||||
d.resolve('');
|
||||
return d.promise;
|
||||
}
|
||||
try {
|
||||
ast = esprima.parse(code, {
|
||||
tolerant: true,
|
||||
@ -607,6 +667,10 @@ TextareaAutoComplete */
|
||||
}
|
||||
} else if (jsMode === JsModes.TS) {
|
||||
try {
|
||||
if (!window.ts) {
|
||||
d.resolve('');
|
||||
return d.promise;
|
||||
}
|
||||
code = ts.transpileModule(code, { reportDiagnostics: true, compilerOptions: { noEmitOnError: true, diagnostics: true, module: ts.ModuleKind.ES2015 } });
|
||||
if (code.diagnostics.length) {
|
||||
|
||||
@ -684,11 +748,13 @@ TextareaAutoComplete */
|
||||
var fileWritten = false;
|
||||
function errorHandler() { utils.log(arguments); }
|
||||
|
||||
// utils.log('writing file ', name);
|
||||
window.webkitRequestFileSystem(window.TEMPORARY, 1024 * 1024 * 5, function(fs){
|
||||
fs.root.getFile(name, { create: true }, function(fileEntry) {
|
||||
fileEntry.createWriter(function(fileWriter) {
|
||||
function onWriteComplete() {
|
||||
if (fileWritten) {
|
||||
// utils.log('file written ', name);
|
||||
return cb();
|
||||
}
|
||||
fileWritten = true;
|
||||
@ -699,7 +765,9 @@ TextareaAutoComplete */
|
||||
}
|
||||
fileWriter.onwriteend = onWriteComplete;
|
||||
// Empty the file contents
|
||||
fileWriter.truncate(0)
|
||||
fileWriter.truncate(0);
|
||||
// utils.log('truncating file ', name);
|
||||
|
||||
}, errorHandler);
|
||||
}, errorHandler);
|
||||
}, errorHandler);
|
||||
@ -716,11 +784,6 @@ TextareaAutoComplete */
|
||||
trackEvent('fn', 'hasCode');
|
||||
trackEvent.hasTrackedCode = true;
|
||||
}
|
||||
// Track when people actually are working.
|
||||
trackEvent.previewCount = (trackEvent.previewCount || 0) + 1;
|
||||
if (trackEvent.previewCount === 4) {
|
||||
trackEvent('fn', 'usingPreview');
|
||||
}
|
||||
|
||||
// we need to store user script in external JS file to prevent inline-script
|
||||
// CSP from affecting it.
|
||||
@ -730,8 +793,6 @@ TextareaAutoComplete */
|
||||
+ chrome.i18n.getMessage('@@extension_id') + '/temporary/' + 'preview.html';
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
scope.setPreviewContent = function (isForced) {
|
||||
@ -740,11 +801,14 @@ TextareaAutoComplete */
|
||||
css: scope.cm.css.getValue(),
|
||||
js: scope.cm.js.getValue()
|
||||
};
|
||||
utils.log('🔎 setPreviewContent', isForced)
|
||||
// If just CSS was changed (and everything shudn't be empty),
|
||||
// change the styles inside the iframe.
|
||||
if (!isForced && currentCode.html === codeInPreview.html && currentCode.js === codeInPreview.js) {
|
||||
computeCss().then(function (css) {
|
||||
frame.contentDocument.querySelector('#webmakerstyle').textContent = css;
|
||||
if (frame.contentDocument.querySelector('#webmakerstyle')) {
|
||||
frame.contentDocument.querySelector('#webmakerstyle').textContent = css;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var htmlPromise = computeHtml();
|
||||
@ -754,6 +818,7 @@ TextareaAutoComplete */
|
||||
createPreviewFile(result[0], result[1], result[2]);
|
||||
});
|
||||
}
|
||||
|
||||
codeInPreview.html = currentCode.html;
|
||||
codeInPreview.css = currentCode.css;
|
||||
codeInPreview.js = currentCode.js;
|
||||
@ -771,7 +836,7 @@ TextareaAutoComplete */
|
||||
var fileContent = getCompleteHtml(html, css, js);
|
||||
|
||||
var d = new Date();
|
||||
var fileName = [ 'web-maker', d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds() ].join('-');
|
||||
var fileName = [ 'web-maker', d.getFullYear(), (d.getMonth() + 1), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds() ].join('-');
|
||||
fileName += '.html';
|
||||
|
||||
if (currentItem.title) {
|
||||
@ -803,6 +868,7 @@ TextareaAutoComplete */
|
||||
keyMap: 'sublime',
|
||||
theme: 'monokai',
|
||||
lint: !!options.lint,
|
||||
tabSize: 2,
|
||||
foldGutter: true,
|
||||
styleActiveLine: true,
|
||||
gutters: options.gutters || [],
|
||||
@ -820,13 +886,46 @@ TextareaAutoComplete */
|
||||
},
|
||||
'Shift-Tab': function(editor) {
|
||||
CodeMirror.commands.indentAuto(editor);
|
||||
},
|
||||
'Tab': function(editor) {
|
||||
var input = $('[data-setting=indentWith]:checked');
|
||||
if (!editor.somethingSelected() && (!input || input.value === 'spaces')) {
|
||||
// softtabs adds spaces. This is required because by default tab key will put tab, but we want
|
||||
// to indent with spaces if `spaces` is preferred mode of indentation.
|
||||
// `somethingSelected` needs to be checked otherwise, all selected code is replaced with softtab.
|
||||
CodeMirror.commands.insertSoftTab(editor);
|
||||
} else {
|
||||
CodeMirror.commands.defaultTab(editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
cm.on('change', function onChange() {
|
||||
cm.on('change', function onChange(editor, change) {
|
||||
clearTimeout(updateTimer);
|
||||
|
||||
updateTimer = setTimeout(function () {
|
||||
scope.setPreviewContent();
|
||||
// This is done so that multiple simultaneous setValue don't trigger too many preview refreshes
|
||||
// and in turn too many file writes on a single file (eg. preview.html).
|
||||
if (change.origin !== 'setValue') {
|
||||
scope.setPreviewContent();
|
||||
|
||||
saveBtn.classList.add('is-marked');
|
||||
unsavedEditCount += 1;
|
||||
if (unsavedEditCount % unsavedEditWarningCount === 0 && unsavedEditCount >= unsavedEditWarningCount) {
|
||||
saveBtn.classList.add('animated');
|
||||
saveBtn.classList.add('wobble');
|
||||
saveBtn.addEventListener('animationend', () => {
|
||||
saveBtn.classList.remove('animated');
|
||||
saveBtn.classList.remove('wobble');
|
||||
});
|
||||
}
|
||||
|
||||
// Track when people actually are working.
|
||||
trackEvent.previewCount = (trackEvent.previewCount || 0) + 1;
|
||||
if (trackEvent.previewCount === 4) {
|
||||
trackEvent('fn', 'usingPreview');
|
||||
}
|
||||
}
|
||||
}, updateDelay);
|
||||
});
|
||||
if (options.noAutocomplete) {
|
||||
@ -853,6 +952,7 @@ TextareaAutoComplete */
|
||||
mode: 'css',
|
||||
gutters: [ 'error-gutter', 'CodeMirror-linenumbers', 'CodeMirror-foldgutter' ]
|
||||
});
|
||||
emmetCodeMirror(scope.cm.css);
|
||||
Inlet(scope.cm.css);
|
||||
scope.cm.js = initEditor(jsCode, {
|
||||
mode: 'javascript',
|
||||
@ -861,7 +961,9 @@ TextareaAutoComplete */
|
||||
Inlet(scope.cm.js);
|
||||
|
||||
function openSettings() {
|
||||
if (chrome.runtime.openOptionsPage) {
|
||||
settingsModal.classList.toggle('is-modal-visible');
|
||||
|
||||
/* if (chrome.runtime.openOptionsPage) {
|
||||
// New way to open options pages, if supported (Chrome 42+).
|
||||
// Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=601997
|
||||
// Until this bug fixes, use the
|
||||
@ -872,25 +974,125 @@ TextareaAutoComplete */
|
||||
chrome.tabs.create({
|
||||
url: 'chrome://extensions?options=' + chrome.i18n.getMessage('@@extension_id')
|
||||
});
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
scope.onModalSettingsLinkClick = function () {
|
||||
scope.onModalSettingsLinkClick = function onModalSettingsLinkClick() {
|
||||
openSettings();
|
||||
trackEvent('ui', 'onboardSettingsBtnClick');
|
||||
}
|
||||
|
||||
scope.onShowInTabClicked = function () {
|
||||
scope.onShowInTabClicked = function onShowInTabClicked() {
|
||||
onboardDontShowInTabOptionBtn.classList.remove('selected');
|
||||
onboardShowInTabOptionBtn.classList.add('selected');
|
||||
trackEvent('ui', 'onboardShowInTabClick');
|
||||
}
|
||||
scope.onDontShowInTabClicked = function () {
|
||||
scope.onDontShowInTabClicked = function onDontShowInTabClicked() {
|
||||
onboardDontShowInTabOptionBtn.classList.add('selected');
|
||||
onboardShowInTabOptionBtn.classList.remove('selected');
|
||||
trackEvent('ui', 'onboardDontShowInTabClick');
|
||||
}
|
||||
|
||||
scope.exportItems = function exportItems(e) {
|
||||
fetchItems().then(function (items) {
|
||||
utils.log(9, items);
|
||||
var d = new Date();
|
||||
var fileName = [ 'web-maker-export', d.getFullYear(), (d.getMonth() + 1), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds() ].join('-');
|
||||
fileName += '.json';
|
||||
var blob = new Blob([ JSON.stringify(items,false,2) ], { type: "application/json;charset=UTF-8" });
|
||||
var a = document.createElement('a');
|
||||
a.href = window.URL.createObjectURL(blob);
|
||||
a.download = fileName;
|
||||
a.style.display = 'none';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
trackEvent('ui', 'exportBtnClicked');
|
||||
});
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function mergeImportedItems(items) {
|
||||
var existingItemIds = [];
|
||||
var toMergeItems = {};
|
||||
items.forEach((item) => {
|
||||
if (savedItems[item.id]) {
|
||||
// Item already exists
|
||||
existingItemIds.push(item.id);
|
||||
} else {
|
||||
utils.log('merging', item.id);
|
||||
toMergeItems[item.id] = item;
|
||||
}
|
||||
});
|
||||
var mergedItemCount = items.length - existingItemIds.length;
|
||||
if (existingItemIds.length) {
|
||||
var shouldReplace = confirm(existingItemIds.length + ' creations already exist. Do you want to replace them?');
|
||||
if (shouldReplace) {
|
||||
utils.log('shouldreplace', shouldReplace);
|
||||
items.forEach((item) => {
|
||||
toMergeItems[item.id] = item;
|
||||
});
|
||||
mergedItemCount = items.length;
|
||||
}
|
||||
}
|
||||
if (mergedItemCount) {
|
||||
// save new items
|
||||
chrome.storage.local.set(toMergeItems, function () {
|
||||
alertsService.add(mergedItemCount + ' creations imported successfully.');
|
||||
});
|
||||
// Push in new item IDs
|
||||
chrome.storage.local.get({
|
||||
items: {}
|
||||
}, function (result) {
|
||||
|
||||
/* eslint-disable guard-for-in */
|
||||
for (var id in toMergeItems) {
|
||||
result.items[id] = true;
|
||||
}
|
||||
chrome.storage.local.set({
|
||||
items: result.items
|
||||
});
|
||||
|
||||
/* eslint-enable guard-for-in */
|
||||
});
|
||||
alertsService.add(mergedItemCount + ' creations imported successfully.');
|
||||
}
|
||||
// FIXME: Move from here
|
||||
toggleSavedItemsPane(false);
|
||||
}
|
||||
|
||||
function onImportFileChange(e) {
|
||||
var file = e.target.files[0];
|
||||
// if (!f.type.match('image.*')) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(progressEvent) {
|
||||
var items;
|
||||
try {
|
||||
items = JSON.parse(progressEvent.target.result);
|
||||
utils.log(items);
|
||||
mergeImportedItems(items);
|
||||
} catch (ex) {
|
||||
alert('Oops! Select file is corrupted.')
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsText(file, 'utf-8');
|
||||
}
|
||||
|
||||
scope.onImportBtnClicked = function exportItems(e) {
|
||||
var input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.style.display = 'none';
|
||||
input.accept = 'accept="application/json';
|
||||
document.body.appendChild(input)
|
||||
input.addEventListener('change', onImportFileChange);
|
||||
input.click();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function saveScreenshot(dataURI) {
|
||||
// convert base64 to raw binary data held in a string
|
||||
// doesn't handle URLEncoded DataURIs
|
||||
@ -911,7 +1113,7 @@ TextareaAutoComplete */
|
||||
var size = blob.size + (1024 / 2);
|
||||
|
||||
var d = new Date();
|
||||
var fileName = [ 'web-maker-screenshot', d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds() ].join('-');
|
||||
var fileName = [ 'web-maker-screenshot', d.getFullYear(), (d.getMonth() + 1), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds() ].join('-');
|
||||
fileName += '.png';
|
||||
|
||||
function onWriteEnd() {
|
||||
@ -977,12 +1179,92 @@ TextareaAutoComplete */
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
// Populate the settings in the settings UI
|
||||
function updateSettingsInUi() {
|
||||
$('[data-setting=preserveLastCode]').checked = prefs.preserveLastCode;
|
||||
$('[data-setting=replaceNewTab]').checked = prefs.replaceNewTab;
|
||||
$('[data-setting=htmlMode]').value = prefs.htmlMode;
|
||||
$('[data-setting=cssMode]').value = prefs.cssMode;
|
||||
$('[data-setting=jsMode]').value = prefs.jsMode;
|
||||
$('[data-setting=indentSize]').value = prefs.indentSize;
|
||||
$('[data-setting=indentWith][value=' + (prefs.indentWith || 'spaces') + ']').checked = true;
|
||||
$('[data-setting=isCodeBlastOn]').checked = prefs.isCodeBlastOn;
|
||||
$('[data-setting=editorTheme]').value = prefs.editorTheme;
|
||||
$('[data-setting=keymap][value=' + (prefs.keymap || 'sublime') + ']').checked = true;
|
||||
$('[data-setting=fontSize]').value = prefs.fontSize || 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles all user triggered preference changes in the UI.
|
||||
*/
|
||||
scope.updateSetting = function updateSetting(e) {
|
||||
// If this was triggered from user interaction, save the setting
|
||||
if (e) {
|
||||
var settingName = e.target.dataset.setting;
|
||||
var obj = {};
|
||||
var el = e.target;
|
||||
utils.log(settingName, (el.type === 'checkbox') ? el.checked : el.value);
|
||||
prefs[settingName] = el.type === 'checkbox' ? el.checked : el.value;
|
||||
obj[settingName] = prefs[settingName];
|
||||
chrome.storage.sync.set(obj, function() {
|
||||
alertsService.add('setting saved');
|
||||
});
|
||||
trackEvent('ui', 'updatePref-' + settingName, prefs[settingName]);
|
||||
}
|
||||
|
||||
htmlCode.querySelector('.CodeMirror').style.fontSize = prefs.fontSize;
|
||||
cssCode.querySelector('.CodeMirror').style.fontSize = prefs.fontSize;
|
||||
jsCode.querySelector('.CodeMirror').style.fontSize = prefs.fontSize;
|
||||
['html', 'js', 'css'].forEach((type) => {
|
||||
scope.cm[type].setOption(
|
||||
'indentWithTabs',
|
||||
$('[data-setting=indentWith]:checked').value !== 'spaces'
|
||||
);
|
||||
|
||||
scope.cm[type].setOption('blastCode', $('[data-setting=isCodeBlastOn]').checked ? { effect: 2, shake: false } : false);
|
||||
scope.cm[type].setOption('indentUnit', $('[data-setting=indentSize]').value);
|
||||
scope.cm[type].setOption('tabSize', $('[data-setting=indentSize]').value);
|
||||
scope.cm[type].setOption('theme', $('[data-setting=editorTheme]').value);
|
||||
// Replace correct css file in LINK tags's href
|
||||
editorThemeLinkTag.href = '/lib/codemirror/theme/' + prefs.editorTheme + '.css';
|
||||
|
||||
scope.cm[type].setOption('keyMap', $('[data-setting=keymap]').value);
|
||||
scope.cm[type].refresh();
|
||||
});
|
||||
};
|
||||
|
||||
scope.onNewBtnClick = function () {
|
||||
trackEvent('ui', 'newBtnClick');
|
||||
if (unsavedEditCount) {
|
||||
var shouldDiscard = confirm('You have unsaved changes. Do you still want to create something new?');
|
||||
if (shouldDiscard) {
|
||||
createNewItem();
|
||||
}
|
||||
} else {
|
||||
createNewItem();
|
||||
}
|
||||
};
|
||||
scope.onOpenBtnClick = function () {
|
||||
trackEvent('ui', 'openBtnClick');
|
||||
openSavedItemsPane();
|
||||
};
|
||||
scope.onSaveBtnClick = function () {
|
||||
trackEvent('ui', 'saveBtnClick', currentItem.id ? 'saved' : 'new');
|
||||
saveItem();
|
||||
};
|
||||
|
||||
function compileNodes() {
|
||||
var nodes = [].slice.call($all('[d-click]'));
|
||||
nodes.forEach(function (el) {
|
||||
el.addEventListener('click', function (e) {
|
||||
scope[el.getAttribute('d-click')].call(window, e)
|
||||
});
|
||||
});
|
||||
nodes = [].slice.call($all('[d-change]'));
|
||||
nodes.forEach(function (el) {
|
||||
el.addEventListener('change', function (e) {
|
||||
scope[el.getAttribute('d-change')].call(window, e)
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
@ -1059,18 +1341,7 @@ TextareaAutoComplete */
|
||||
saveFile();
|
||||
trackEvent('ui', 'saveHtmlClick');
|
||||
});
|
||||
utils.onButtonClick(openBtn, function () {
|
||||
openSavedItemsPane();
|
||||
trackEvent('ui', 'openBtnClick');
|
||||
});
|
||||
utils.onButtonClick(saveBtn, function () {
|
||||
trackEvent('ui', 'saveBtnClick', currentItem.id ? 'saved' : 'new');
|
||||
saveItem();
|
||||
});
|
||||
utils.onButtonClick(newBtn, function () {
|
||||
createNewItem();
|
||||
trackEvent('ui', 'newBtnClick');
|
||||
});
|
||||
|
||||
utils.onButtonClick(savedItemsPaneCloseBtn, toggleSavedItemsPane);
|
||||
utils.onButtonClick(savedItemsPane, function (e) {
|
||||
if (e.target.classList.contains('js-saved-item-tile')) {
|
||||
@ -1080,7 +1351,6 @@ TextareaAutoComplete */
|
||||
toggleSavedItemsPane();
|
||||
}
|
||||
if (e.target.classList.contains('js-saved-item-tile__close-btn')) {
|
||||
utils.log('removing', e.target.parentElement)
|
||||
removeItem(e.target.parentElement.dataset.itemId);
|
||||
}
|
||||
});
|
||||
@ -1101,11 +1371,11 @@ TextareaAutoComplete */
|
||||
var currentMode = type === 'html' ? htmlMode : (type === 'css' ? cssMode : jsMode);
|
||||
if (currentMode !== mode) {
|
||||
if (type === 'html') {
|
||||
updateHtmlMode(mode);
|
||||
updateHtmlMode(mode).then(() => scope.setPreviewContent(true));
|
||||
} else if (type === 'js') {
|
||||
updateJsMode(mode);
|
||||
updateJsMode(mode).then(() => scope.setPreviewContent(true));
|
||||
} else if (type === 'css') {
|
||||
updateCssMode(mode);
|
||||
updateCssMode(mode).then(() => scope.setPreviewContent(true));
|
||||
}
|
||||
trackEvent('ui', 'updateCodeMode', mode);
|
||||
}
|
||||
@ -1229,11 +1499,19 @@ TextareaAutoComplete */
|
||||
// Get synced `preserveLastCode` setting to get back last code (or not).
|
||||
chrome.storage.sync.get({
|
||||
preserveLastCode: true,
|
||||
replaceNewTab: false,
|
||||
htmlMode: 'html',
|
||||
jsMode: 'js',
|
||||
cssMode: 'css'
|
||||
cssMode: 'css',
|
||||
isCodeBlastOn: false,
|
||||
indentWith: 'spaces',
|
||||
indentSize: 2,
|
||||
editorTheme: 'monokai',
|
||||
keymap: 'sublime',
|
||||
fontSize: 16
|
||||
}, function syncGetCallback(result) {
|
||||
if (result.preserveLastCode && lastCode) {
|
||||
unsavedEditCount = 0;
|
||||
if (lastCode.id) {
|
||||
chrome.storage.local.get(lastCode.id, function (itemResult) {
|
||||
utils.log('Load item ', lastCode.id)
|
||||
@ -1248,9 +1526,20 @@ TextareaAutoComplete */
|
||||
} else {
|
||||
createNewItem();
|
||||
}
|
||||
prefs.htmlMode = result.htmlmode;
|
||||
prefs.preserveLastCode = result.preserveLastCode;
|
||||
prefs.replaceNewTab = result.replaceNewTab;
|
||||
prefs.htmlMode = result.htmlMode;
|
||||
prefs.cssMode = result.cssMode;
|
||||
prefs.jsMode = result.jsMode;
|
||||
prefs.isCodeBlastOn = result.isCodeBlastOn;
|
||||
prefs.indentSize = result.indentSize;
|
||||
prefs.indentWith = result.indentWith;
|
||||
prefs.editorTheme = result.editorTheme;
|
||||
prefs.keymap = result.keymap;
|
||||
prefs.fontSize = result.fontSize;
|
||||
|
||||
updateSettingsInUi();
|
||||
scope.updateSetting();
|
||||
});
|
||||
|
||||
// Check for new version notifications
|
||||
@ -1280,6 +1569,59 @@ TextareaAutoComplete */
|
||||
}
|
||||
});
|
||||
|
||||
var options = '';
|
||||
[
|
||||
'3024-day',
|
||||
'3024-night',
|
||||
'abcdef',
|
||||
'ambiance',
|
||||
'base16-dark',
|
||||
'base16-light',
|
||||
'bespin',
|
||||
'blackboard',
|
||||
'cobalt',
|
||||
'colorforth',
|
||||
'dracula',
|
||||
'duotone-dark',
|
||||
'duotone-light',
|
||||
'eclipse',
|
||||
'elegant',
|
||||
'erlang-dark',
|
||||
'hopscotch',
|
||||
'icecoder',
|
||||
'isotope',
|
||||
'lesser-dark',
|
||||
'liquibyte',
|
||||
'material',
|
||||
'mbo',
|
||||
'mdn-like',
|
||||
'midnight',
|
||||
'monokai',
|
||||
'neat',
|
||||
'neo',
|
||||
'night',
|
||||
'panda-syntax',
|
||||
'paraiso-dark',
|
||||
'paraiso-light',
|
||||
'pastel-on-dark',
|
||||
'railscasts',
|
||||
'rubyblue',
|
||||
'seti',
|
||||
'solarized dark',
|
||||
'solarized light',
|
||||
'the-matrix',
|
||||
'tomorrow-night-bright',
|
||||
'tomorrow-night-eighties',
|
||||
'ttcn',
|
||||
'twilight',
|
||||
'vibrant-ink',
|
||||
'xq-dark',
|
||||
'xq-light',
|
||||
'yeti',
|
||||
'zenburn'
|
||||
].forEach((theme) => { options += '<option value="' + theme + '">' + theme + '</option>'; });
|
||||
document.querySelector('[data-setting="editorTheme"]').innerHTML = options;
|
||||
|
||||
requestAnimationFrame(compileNodes);
|
||||
}
|
||||
|
||||
|
@ -31,12 +31,27 @@ a { text-decoration: none; color: crimson; cursor: pointer; }
|
||||
.fr { float: right; }
|
||||
.relative { position: relative; }
|
||||
.tac { text-align: center; }
|
||||
.va-m { vertical-align: middle; }
|
||||
.full-width { width: 100%; }
|
||||
.opacity--30 { opacity: 0.3; }
|
||||
.pointer-none { pointer-events: none; }
|
||||
|
||||
.ml-1 { margin-left: 1rem; }
|
||||
hr {
|
||||
background: 0;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #dedede;
|
||||
}
|
||||
label {
|
||||
cursor: pointer;
|
||||
}
|
||||
[class*="hint--"]:after {
|
||||
text-transform: none;
|
||||
font-weight: normal;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.line {
|
||||
display: block;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.caret {
|
||||
display: inline-block;
|
||||
@ -51,7 +66,7 @@ a { text-decoration: none; color: crimson; cursor: pointer; }
|
||||
a > svg {
|
||||
fill: rgba(255, 255, 255, 0.2)
|
||||
}
|
||||
select, input[type="text"], textarea {
|
||||
select, input[type="text"], input[type="number"], textarea {
|
||||
padding: 3px 5px;
|
||||
font-size: inherit;
|
||||
}
|
||||
@ -222,7 +237,7 @@ select, input[type="text"], textarea {
|
||||
.cm-s-monokai .CodeMirror-guttermarker-subtle {
|
||||
opacity: 0.4;
|
||||
}
|
||||
.CodeMirror-activeline-background, .CodeMirror-activeline-gutter {
|
||||
.cm-s-monokai .CodeMirror-activeline-background, .cm-s-monokai .CodeMirror-activeline-gutter {
|
||||
background: rgba(0,0,0,0.1) !important;
|
||||
}
|
||||
.CodeMirror-guttermarker-subtle {
|
||||
@ -258,7 +273,7 @@ li.CodeMirror-hint-active {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
color: rgba(255, 255, 255, 0.45);
|
||||
border-top: 1px solid rgba(255,255,255,0.14);
|
||||
line-height: 20px;
|
||||
/*line-height: 20px;*/
|
||||
}
|
||||
.main-header {
|
||||
border: 0;
|
||||
@ -266,17 +281,27 @@ li.CodeMirror-hint-active {
|
||||
}
|
||||
.main-header__btn-wrap > a {
|
||||
font-size: 0.8em;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
height: 20px;
|
||||
letter-spacing: 0.6px;
|
||||
color: #9297B3;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(146, 151, 179, 0.33);
|
||||
margin-left: 10px;
|
||||
padding: 0px 5px;
|
||||
padding: 0px 8px;
|
||||
border: 1px solid rgba(0,0,0,.9);
|
||||
background: linear-gradient(180deg, rgba(0,0,0,0.5) 0, rgba(255,255,255,0.1) 100%);
|
||||
/*text-shadow: 0px 1px 1px rgba(0,0,0,1);*/
|
||||
box-shadow: 0 -1px 0px 0 rgba(255,255,255,0.15);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.main-header__btn-wrap > a > svg {
|
||||
fill: #9297B3;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.main-header__btn-wrap > a.is-marked > svg {
|
||||
fill: crimson;
|
||||
}
|
||||
.main-header__btn-wrap > a:hover {
|
||||
border-color: rgba(146, 151, 179, 0.5);
|
||||
}
|
||||
@ -290,9 +315,11 @@ li.CodeMirror-hint-active {
|
||||
vertical-align: middle;
|
||||
-webkit-filter: grayscale(0.9);
|
||||
transition: 0.4s ease;
|
||||
opacity: 0.3;
|
||||
}
|
||||
.footer:hover .logo {
|
||||
-webkit-filter: grayscale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
.footer__right {
|
||||
font-size: 0;
|
||||
@ -351,8 +378,8 @@ li.CodeMirror-hint-active {
|
||||
position: fixed;
|
||||
top: 5vh;
|
||||
left: 50%;
|
||||
width: 60vw;
|
||||
margin-left: -30vw;
|
||||
width: 68vw;
|
||||
margin-left: -34vw;
|
||||
max-width: 90vw;
|
||||
height: auto;
|
||||
z-index: 2000;
|
||||
@ -373,6 +400,7 @@ li.CodeMirror-hint-active {
|
||||
opacity: 0;
|
||||
padding: 2em;
|
||||
font-size: 1.3em;
|
||||
line-height: 1.4;
|
||||
max-height: 90vh;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
@ -736,3 +764,39 @@ li.CodeMirror-hint-active {
|
||||
right: 10px;
|
||||
bottom: 10px;
|
||||
}
|
||||
@keyframes wobble {
|
||||
from {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
15% {
|
||||
transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
|
||||
}
|
||||
|
||||
30% {
|
||||
transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
|
||||
}
|
||||
|
||||
45% {
|
||||
transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
.animated {
|
||||
animation-duration: 1s;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
.wobble {
|
||||
animation-name: wobble;
|
||||
}
|
||||
|
28
test-scenarios.md
Normal file
28
test-scenarios.md
Normal file
@ -0,0 +1,28 @@
|
||||
## Editor
|
||||
|
||||
- Tab should insert tab when nothing selected,
|
||||
- Tab should indent when something is selected.
|
||||
|
||||
## Logic
|
||||
|
||||
- `for`, `while` & `dowhile` loops should be instrumented in the generated JavaScript code.
|
||||
- Import should confirm the overriding of existing items.
|
||||
- Opening a smaller DOM item shouldn't show left over HTML from a previously open bigger DOM item.
|
||||
|
||||
## Interface
|
||||
|
||||
- 'New' button should create a new item if no unsaved changes present, otherwise ask confirmation.
|
||||
- 'Save' button click should save the current work with a notification.
|
||||
- Ctrl/Cmd+S should save the current work with a notification.
|
||||
- 'Open' button click should open saved creations panel.
|
||||
- Ctrl/Cmd+O should open saved creations panel.
|
||||
- Clicking on an item in saved items pane should open that item in the editor.
|
||||
- Clicking the close button in the saved item tile should confirm first, and then remove that item from DOM & storage.
|
||||
- If the item being removed is open in the editor, a new item should be created & opened after removal.
|
||||
- Clicking the *export* button should download a JSON formatted export file of saved items.
|
||||
- Clicking on *import* button should ask to select a JSON file to import.
|
||||
|
||||
## Settings
|
||||
|
||||
- Each setting change should update the corresponding key in chrome sync storage
|
||||
- Changing fontSize, theme should reflect in the editor as soon as it is changed and focused out.
|
Loading…
x
Reference in New Issue
Block a user