mirror of
https://github.com/chinchang/web-maker.git
synced 2025-05-04 17:46:42 +02:00
commit
35658fcd17
@ -99,7 +99,7 @@
|
||||
"no-implicit-coercion": "error",
|
||||
"no-implicit-globals": "off",
|
||||
"no-implied-eval": "error",
|
||||
"no-inline-comments": "error",
|
||||
"no-inline-comments": "off",
|
||||
"no-inner-declarations": [
|
||||
"error",
|
||||
"functions"
|
||||
@ -118,7 +118,7 @@
|
||||
"no-multiple-empty-lines": "error",
|
||||
"no-native-reassign": "error",
|
||||
"no-negated-condition": "off",
|
||||
"no-nested-ternary": "error",
|
||||
"no-nested-ternary": "off",
|
||||
"no-new": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-object": "error",
|
||||
@ -178,9 +178,9 @@
|
||||
"no-with": "error",
|
||||
"object-curly-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
"always"
|
||||
],
|
||||
"object-property-newline": "error",
|
||||
"object-property-newline": "off",
|
||||
"object-shorthand": "off",
|
||||
"one-var": "off",
|
||||
"one-var-declaration-per-line": "error",
|
||||
@ -195,7 +195,7 @@
|
||||
"padded-blocks": "off",
|
||||
"prefer-arrow-callback": "off",
|
||||
"prefer-const": "error",
|
||||
"prefer-reflect": "error",
|
||||
"prefer-reflect": "off",
|
||||
"prefer-rest-params": "off",
|
||||
"prefer-spread": "error",
|
||||
"prefer-template": "off",
|
||||
@ -235,7 +235,7 @@
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"valid-jsdoc": "error",
|
||||
"valid-jsdoc": "off",
|
||||
"vars-on-top": "off",
|
||||
"wrap-regex": "error",
|
||||
"yield-star-spacing": "error",
|
||||
@ -248,6 +248,17 @@
|
||||
"chrome": true,
|
||||
"CodeMirror": true,
|
||||
"Split": true,
|
||||
"emmetCodeMirror": true
|
||||
"emmetCodeMirror": true,
|
||||
"deferred": true,
|
||||
"$": true,
|
||||
"$all": true,
|
||||
"CoffeeScript": true,
|
||||
"Babel": true,
|
||||
"Sass": true,
|
||||
"less": true,
|
||||
"marked": true,
|
||||
"jade": true,
|
||||
"loadJS": true,
|
||||
"Promise": true
|
||||
}
|
||||
}
|
BIN
src/Inconsolata-Regular.ttf
Executable file
BIN
src/Inconsolata-Regular.ttf
Executable file
Binary file not shown.
12
src/deferred.js
Normal file
12
src/deferred.js
Normal file
@ -0,0 +1,12 @@
|
||||
(function() {
|
||||
window.deferred = function () {
|
||||
var d = {};
|
||||
var promise = new Promise(function (resolve, reject) {
|
||||
d.resolve = resolve;
|
||||
d.reject = reject;
|
||||
});
|
||||
|
||||
d.promise = promise;
|
||||
return Object.assign(d, promise);
|
||||
};
|
||||
})();
|
30
src/dropdown.js
Normal file
30
src/dropdown.js
Normal file
@ -0,0 +1,30 @@
|
||||
// Dropdown.js
|
||||
|
||||
(function($all) {
|
||||
var openDropdown;
|
||||
|
||||
// Closes all dropdowns except the passed one.
|
||||
function closeOpenDropdown(except) {
|
||||
if (openDropdown && (!except || except !== openDropdown)) {
|
||||
openDropdown.classList.remove('open');
|
||||
openDropdown = null;
|
||||
}
|
||||
}
|
||||
function init() {
|
||||
var dropdowns = [].slice.call($all('[dropdown]'));
|
||||
dropdowns.forEach(function (dropdown) {
|
||||
dropdown.addEventListener('click', function (e) {
|
||||
closeOpenDropdown(e.currentTarget);
|
||||
e.currentTarget.classList.toggle('open');
|
||||
openDropdown = e.currentTarget;
|
||||
e.stopPropagation();
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('click', function () {
|
||||
closeOpenDropdown();
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
})($all);
|
138
src/index.html
138
src/index.html
@ -5,8 +5,15 @@
|
||||
<link rel="stylesheet" href="lib/codemirror/lib/codemirror.css">
|
||||
<link rel="stylesheet" href="lib/codemirror/theme/monokai.css">
|
||||
<link rel="stylesheet" href="lib/hint.min.css">
|
||||
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'Inconsolata';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Inconsolata'), url(../Inconsolata-Regular.ttf) format('truetype');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@ -29,6 +36,16 @@
|
||||
.fr {
|
||||
float: right;
|
||||
}
|
||||
.caret {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 6px solid transparent;
|
||||
border-top-color: currentColor;
|
||||
position: relative;
|
||||
top: 5px;
|
||||
margin-left: 7px;
|
||||
}
|
||||
.main-container {
|
||||
position: absolute;
|
||||
left: 0; right: 0;
|
||||
@ -59,9 +76,9 @@
|
||||
height: 33%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
animation: pop-in 0.4s cubic-bezier(.71,1.7,.77,1.24) forwards 0.2s;
|
||||
animation: pop-in 0.4s ease forwards 0.2s;
|
||||
opacity: 0;
|
||||
/*animation: pop-in 0.4s cubic-bezier(.71,1.7,.77,1.24) forwards 0.2s;*/
|
||||
/*animation: pop-in 0.4s ease forwards 0.2s;*/
|
||||
/*opacity: 0;*/
|
||||
}
|
||||
.layout-2 .code-wrap {
|
||||
height: auto;
|
||||
@ -74,17 +91,12 @@
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.code-wrap:after {
|
||||
content: attr(data-type);
|
||||
text-transform: uppercase;
|
||||
font-size: 65px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
color: rgba(255,255,255,0.04);
|
||||
left: 52px;
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
.code-wrap__header {
|
||||
padding: 5px 20px;
|
||||
background: rgba(0,0,0,0.55);
|
||||
color: #888;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.3);
|
||||
font-weight: bold;
|
||||
}
|
||||
@keyframes pop-in {
|
||||
from { transform: scale(0.9); opacity: 0; }
|
||||
@ -94,9 +106,12 @@
|
||||
/* Codemirror */
|
||||
.Codemirror {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
height: calc(100% - 25px); /* 25px for header */
|
||||
font-size: 16px;
|
||||
}
|
||||
.Codemirror pre {
|
||||
font-family: 'Inconsolata', monospace;
|
||||
}
|
||||
.cm-s-monokai .CodeMirror-linenumber {
|
||||
color:rgba(255,255,255,0.2);
|
||||
}
|
||||
@ -167,6 +182,9 @@
|
||||
.mode-btn.selected svg {
|
||||
fill: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
.gutter {
|
||||
background: rgba(0,0,0,0.2);
|
||||
}
|
||||
.gutter-horizontal {
|
||||
cursor: ew-resize;
|
||||
}
|
||||
@ -274,6 +292,49 @@
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
}
|
||||
.btn-group {
|
||||
position: relative;
|
||||
}
|
||||
.btn-group {
|
||||
cursor: pointer;
|
||||
}
|
||||
.dropdown__menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
min-width: 200px;
|
||||
display: block;
|
||||
list-style: none;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: 0.25s ease;
|
||||
transform: translateY(10px);
|
||||
z-index: 5;
|
||||
background: white;
|
||||
}
|
||||
.dropdown__menu > li > a {
|
||||
display: block;
|
||||
padding: 15px;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
}
|
||||
.dropdown__menu > li > a:hover {
|
||||
background: #ff8c00;
|
||||
color: white;
|
||||
}
|
||||
.dropdown__menu > li:not(:last-child) {
|
||||
border-bottom: 1px solid rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.open .dropdown__menu {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@ -281,9 +342,42 @@
|
||||
<div class="main-container">
|
||||
<div class="content-wrap flex flex-grow">
|
||||
<div class="code-side" id="js-code-side">
|
||||
<div id="js-html-code" data-type="html" class="code-wrap"></div>
|
||||
<div id="js-css-code" data-type="css" class="code-wrap"></div>
|
||||
<div id="js-js-code" data-type="js" class="code-wrap"></div>
|
||||
<div id="js-html-code" data-type="html" class="code-wrap">
|
||||
<div class="code-wrap__header">
|
||||
<div class="btn-group" dropdown>
|
||||
<span id="js-html-mode-label">HTML</span><span class="caret"></span>
|
||||
<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>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="js-css-code" data-type="css" class="code-wrap">
|
||||
<div class="code-wrap__header">
|
||||
<div class="btn-group" dropdown>
|
||||
<span id="js-css-mode-label">CSS</span><span class="caret"></span>
|
||||
<ul class="js-modes-menu dropdown__menu">
|
||||
<li><a data-type="css" data-mode="css">CSS</a></li>
|
||||
<li><a data-type="css" data-mode="scss">SCSS</a></li>
|
||||
<li><a data-type="css" data-mode="less">LESS</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="js-js-code" data-type="js" class="code-wrap">
|
||||
<div class="code-wrap__header">
|
||||
<div class="btn-group" dropdown>
|
||||
<span id="js-js-mode-label">JS</span><span class="caret"></span>
|
||||
<ul class="js-modes-menu dropdown__menu">
|
||||
<li><a data-type="js" data-mode="js">JS</a></li>
|
||||
<li><a data-type="js" data-mode="coffee">CoffeeScript</a></li>
|
||||
<li><a data-type="js" data-mode="es6">ES6 (Babel)</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-side" id="js-demo-side">
|
||||
<iframe src="about://blank" frameborder="0" id="demo-frame"></iframe>
|
||||
@ -421,6 +515,8 @@
|
||||
<script src="lib/codemirror/addon/edit/matchbrackets.js"></script>
|
||||
<script src="lib/codemirror/addon/edit/closebrackets.js"></script>
|
||||
<script src="lib/codemirror/addon/edit/closetag.js"></script>
|
||||
<script src="lib/codemirror/addon/comment/comment.js"></script>
|
||||
<script src="lib/codemirror/addon/mode/loadmode.js"></script>
|
||||
|
||||
<script src="lib/codemirror/mode/xml/xml.js"></script>
|
||||
<script src="lib/codemirror/mode/javascript/javascript.js"></script>
|
||||
@ -430,7 +526,11 @@
|
||||
<script src="lib/emmet.js"></script>
|
||||
|
||||
<script src="lib/split.js"></script>
|
||||
|
||||
<script src="deferred.js"></script>
|
||||
<script src="loader.js"></script>
|
||||
<script src="script.js"></script>
|
||||
<script src="dropdown.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
32
src/lib/babel.min.js
vendored
Normal file
32
src/lib/babel.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
740
src/lib/codemirror/mode/coffeescript/index.html
vendored
740
src/lib/codemirror/mode/coffeescript/index.html
vendored
@ -1,740 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: CoffeeScript mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="coffeescript.js"></script>
|
||||
<style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">CoffeeScript</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>CoffeeScript mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
# CoffeeScript mode for CodeMirror
|
||||
# Copyright (c) 2011 Jeff Pickhardt, released under
|
||||
# the MIT License.
|
||||
#
|
||||
# Modified from the Python CodeMirror mode, which also is
|
||||
# under the MIT License Copyright (c) 2010 Timothy Farrell.
|
||||
#
|
||||
# The following script, Underscore.coffee, is used to
|
||||
# demonstrate CoffeeScript mode for CodeMirror.
|
||||
#
|
||||
# To download CoffeeScript mode for CodeMirror, go to:
|
||||
# https://github.com/pickhardt/coffeescript-codemirror-mode
|
||||
|
||||
# **Underscore.coffee
|
||||
# (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.**
|
||||
# Underscore is freely distributable under the terms of the
|
||||
# [MIT license](http://en.wikipedia.org/wiki/MIT_License).
|
||||
# Portions of Underscore are inspired by or borrowed from
|
||||
# [Prototype.js](http://prototypejs.org/api), Oliver Steele's
|
||||
# [Functional](http://osteele.com), and John Resig's
|
||||
# [Micro-Templating](http://ejohn.org).
|
||||
# For all details and documentation:
|
||||
# http://documentcloud.github.com/underscore/
|
||||
|
||||
|
||||
# Baseline setup
|
||||
# --------------
|
||||
|
||||
# Establish the root object, `window` in the browser, or `global` on the server.
|
||||
root = this
|
||||
|
||||
|
||||
# Save the previous value of the `_` variable.
|
||||
previousUnderscore = root._
|
||||
|
||||
### Multiline
|
||||
comment
|
||||
###
|
||||
|
||||
# Establish the object that gets thrown to break out of a loop iteration.
|
||||
# `StopIteration` is SOP on Mozilla.
|
||||
breaker = if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
|
||||
|
||||
|
||||
#### Docco style single line comment (title)
|
||||
|
||||
|
||||
# Helper function to escape **RegExp** contents, because JS doesn't have one.
|
||||
escapeRegExp = (string) -> string.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1')
|
||||
|
||||
|
||||
# Save bytes in the minified (but not gzipped) version:
|
||||
ArrayProto = Array.prototype
|
||||
ObjProto = Object.prototype
|
||||
|
||||
|
||||
# Create quick reference variables for speed access to core prototypes.
|
||||
slice = ArrayProto.slice
|
||||
unshift = ArrayProto.unshift
|
||||
toString = ObjProto.toString
|
||||
hasOwnProperty = ObjProto.hasOwnProperty
|
||||
propertyIsEnumerable = ObjProto.propertyIsEnumerable
|
||||
|
||||
|
||||
# All **ECMA5** native implementations we hope to use are declared here.
|
||||
nativeForEach = ArrayProto.forEach
|
||||
nativeMap = ArrayProto.map
|
||||
nativeReduce = ArrayProto.reduce
|
||||
nativeReduceRight = ArrayProto.reduceRight
|
||||
nativeFilter = ArrayProto.filter
|
||||
nativeEvery = ArrayProto.every
|
||||
nativeSome = ArrayProto.some
|
||||
nativeIndexOf = ArrayProto.indexOf
|
||||
nativeLastIndexOf = ArrayProto.lastIndexOf
|
||||
nativeIsArray = Array.isArray
|
||||
nativeKeys = Object.keys
|
||||
|
||||
|
||||
# Create a safe reference to the Underscore object for use below.
|
||||
_ = (obj) -> new wrapper(obj)
|
||||
|
||||
|
||||
# Export the Underscore object for **CommonJS**.
|
||||
if typeof(exports) != 'undefined' then exports._ = _
|
||||
|
||||
|
||||
# Export Underscore to global scope.
|
||||
root._ = _
|
||||
|
||||
|
||||
# Current version.
|
||||
_.VERSION = '1.1.0'
|
||||
|
||||
|
||||
# Collection Functions
|
||||
# --------------------
|
||||
|
||||
# The cornerstone, an **each** implementation.
|
||||
# Handles objects implementing **forEach**, arrays, and raw objects.
|
||||
_.each = (obj, iterator, context) ->
|
||||
try
|
||||
if nativeForEach and obj.forEach is nativeForEach
|
||||
obj.forEach iterator, context
|
||||
else if _.isNumber obj.length
|
||||
iterator.call context, obj[i], i, obj for i in [0...obj.length]
|
||||
else
|
||||
iterator.call context, val, key, obj for own key, val of obj
|
||||
catch e
|
||||
throw e if e isnt breaker
|
||||
obj
|
||||
|
||||
|
||||
# Return the results of applying the iterator to each element. Use JavaScript
|
||||
# 1.6's version of **map**, if possible.
|
||||
_.map = (obj, iterator, context) ->
|
||||
return obj.map(iterator, context) if nativeMap and obj.map is nativeMap
|
||||
results = []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
# **Reduce** builds up a single result from a list of values. Also known as
|
||||
# **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.
|
||||
_.reduce = (obj, iterator, memo, context) ->
|
||||
if nativeReduce and obj.reduce is nativeReduce
|
||||
iterator = _.bind iterator, context if context
|
||||
return obj.reduce iterator, memo
|
||||
_.each obj, (value, index, list) ->
|
||||
memo = iterator.call context, memo, value, index, list
|
||||
memo
|
||||
|
||||
|
||||
# The right-associative version of **reduce**, also known as **foldr**. Uses
|
||||
# JavaScript 1.8's version of **reduceRight**, if available.
|
||||
_.reduceRight = (obj, iterator, memo, context) ->
|
||||
if nativeReduceRight and obj.reduceRight is nativeReduceRight
|
||||
iterator = _.bind iterator, context if context
|
||||
return obj.reduceRight iterator, memo
|
||||
reversed = _.clone(_.toArray(obj)).reverse()
|
||||
_.reduce reversed, iterator, memo, context
|
||||
|
||||
|
||||
# Return the first value which passes a truth test.
|
||||
_.detect = (obj, iterator, context) ->
|
||||
result = null
|
||||
_.each obj, (value, index, list) ->
|
||||
if iterator.call context, value, index, list
|
||||
result = value
|
||||
_.breakLoop()
|
||||
result
|
||||
|
||||
|
||||
# Return all the elements that pass a truth test. Use JavaScript 1.6's
|
||||
# **filter**, if it exists.
|
||||
_.filter = (obj, iterator, context) ->
|
||||
return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter
|
||||
results = []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push value if iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
# Return all the elements for which a truth test fails.
|
||||
_.reject = (obj, iterator, context) ->
|
||||
results = []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push value if not iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
# Determine whether all of the elements match a truth test. Delegate to
|
||||
# JavaScript 1.6's **every**, if it is present.
|
||||
_.every = (obj, iterator, context) ->
|
||||
iterator ||= _.identity
|
||||
return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
|
||||
result = true
|
||||
_.each obj, (value, index, list) ->
|
||||
_.breakLoop() unless (result = result and iterator.call(context, value, index, list))
|
||||
result
|
||||
|
||||
|
||||
# Determine if at least one element in the object matches a truth test. Use
|
||||
# JavaScript 1.6's **some**, if it exists.
|
||||
_.some = (obj, iterator, context) ->
|
||||
iterator ||= _.identity
|
||||
return obj.some iterator, context if nativeSome and obj.some is nativeSome
|
||||
result = false
|
||||
_.each obj, (value, index, list) ->
|
||||
_.breakLoop() if (result = iterator.call(context, value, index, list))
|
||||
result
|
||||
|
||||
|
||||
# Determine if a given value is included in the array or object,
|
||||
# based on `===`.
|
||||
_.include = (obj, target) ->
|
||||
return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf
|
||||
return true for own key, val of obj when val is target
|
||||
false
|
||||
|
||||
|
||||
# Invoke a method with arguments on every item in a collection.
|
||||
_.invoke = (obj, method) ->
|
||||
args = _.rest arguments, 2
|
||||
(if method then val[method] else val).apply(val, args) for val in obj
|
||||
|
||||
|
||||
# Convenience version of a common use case of **map**: fetching a property.
|
||||
_.pluck = (obj, key) ->
|
||||
_.map(obj, (val) -> val[key])
|
||||
|
||||
|
||||
# Return the maximum item or (item-based computation).
|
||||
_.max = (obj, iterator, context) ->
|
||||
return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
|
||||
result = computed: -Infinity
|
||||
_.each obj, (value, index, list) ->
|
||||
computed = if iterator then iterator.call(context, value, index, list) else value
|
||||
computed >= result.computed and (result = {value: value, computed: computed})
|
||||
result.value
|
||||
|
||||
|
||||
# Return the minimum element (or element-based computation).
|
||||
_.min = (obj, iterator, context) ->
|
||||
return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
|
||||
result = computed: Infinity
|
||||
_.each obj, (value, index, list) ->
|
||||
computed = if iterator then iterator.call(context, value, index, list) else value
|
||||
computed < result.computed and (result = {value: value, computed: computed})
|
||||
result.value
|
||||
|
||||
|
||||
# Sort the object's values by a criterion produced by an iterator.
|
||||
_.sortBy = (obj, iterator, context) ->
|
||||
_.pluck(((_.map obj, (value, index, list) ->
|
||||
{value: value, criteria: iterator.call(context, value, index, list)}
|
||||
).sort((left, right) ->
|
||||
a = left.criteria; b = right.criteria
|
||||
if a < b then -1 else if a > b then 1 else 0
|
||||
)), 'value')
|
||||
|
||||
|
||||
# Use a comparator function to figure out at what index an object should
|
||||
# be inserted so as to maintain order. Uses binary search.
|
||||
_.sortedIndex = (array, obj, iterator) ->
|
||||
iterator ||= _.identity
|
||||
low = 0
|
||||
high = array.length
|
||||
while low < high
|
||||
mid = (low + high) >> 1
|
||||
if iterator(array[mid]) < iterator(obj) then low = mid + 1 else high = mid
|
||||
low
|
||||
|
||||
|
||||
# Convert anything iterable into a real, live array.
|
||||
_.toArray = (iterable) ->
|
||||
return [] if (!iterable)
|
||||
return iterable.toArray() if (iterable.toArray)
|
||||
return iterable if (_.isArray(iterable))
|
||||
return slice.call(iterable) if (_.isArguments(iterable))
|
||||
_.values(iterable)
|
||||
|
||||
|
||||
# Return the number of elements in an object.
|
||||
_.size = (obj) -> _.toArray(obj).length
|
||||
|
||||
|
||||
# Array Functions
|
||||
# ---------------
|
||||
|
||||
# Get the first element of an array. Passing `n` will return the first N
|
||||
# values in the array. Aliased as **head**. The `guard` check allows it to work
|
||||
# with **map**.
|
||||
_.first = (array, n, guard) ->
|
||||
if n and not guard then slice.call(array, 0, n) else array[0]
|
||||
|
||||
|
||||
# Returns everything but the first entry of the array. Aliased as **tail**.
|
||||
# Especially useful on the arguments object. Passing an `index` will return
|
||||
# the rest of the values in the array from that index onward. The `guard`
|
||||
# check allows it to work with **map**.
|
||||
_.rest = (array, index, guard) ->
|
||||
slice.call(array, if _.isUndefined(index) or guard then 1 else index)
|
||||
|
||||
|
||||
# Get the last element of an array.
|
||||
_.last = (array) -> array[array.length - 1]
|
||||
|
||||
|
||||
# Trim out all falsy values from an array.
|
||||
_.compact = (array) -> item for item in array when item
|
||||
|
||||
|
||||
# Return a completely flattened version of an array.
|
||||
_.flatten = (array) ->
|
||||
_.reduce array, (memo, value) ->
|
||||
return memo.concat(_.flatten(value)) if _.isArray value
|
||||
memo.push value
|
||||
memo
|
||||
, []
|
||||
|
||||
|
||||
# Return a version of the array that does not contain the specified value(s).
|
||||
_.without = (array) ->
|
||||
values = _.rest arguments
|
||||
val for val in _.toArray(array) when not _.include values, val
|
||||
|
||||
|
||||
# Produce a duplicate-free version of the array. If the array has already
|
||||
# been sorted, you have the option of using a faster algorithm.
|
||||
_.uniq = (array, isSorted) ->
|
||||
memo = []
|
||||
for el, i in _.toArray array
|
||||
memo.push el if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
|
||||
memo
|
||||
|
||||
|
||||
# Produce an array that contains every item shared between all the
|
||||
# passed-in arrays.
|
||||
_.intersect = (array) ->
|
||||
rest = _.rest arguments
|
||||
_.select _.uniq(array), (item) ->
|
||||
_.all rest, (other) ->
|
||||
_.indexOf(other, item) >= 0
|
||||
|
||||
|
||||
# Zip together multiple lists into a single array -- elements that share
|
||||
# an index go together.
|
||||
_.zip = ->
|
||||
length = _.max _.pluck arguments, 'length'
|
||||
results = new Array length
|
||||
for i in [0...length]
|
||||
results[i] = _.pluck arguments, String i
|
||||
results
|
||||
|
||||
|
||||
# If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),
|
||||
# we need this function. Return the position of the first occurrence of an
|
||||
# item in an array, or -1 if the item is not included in the array.
|
||||
_.indexOf = (array, item) ->
|
||||
return array.indexOf item if nativeIndexOf and array.indexOf is nativeIndexOf
|
||||
i = 0; l = array.length
|
||||
while l - i
|
||||
if array[i] is item then return i else i++
|
||||
-1
|
||||
|
||||
|
||||
# Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,
|
||||
# if possible.
|
||||
_.lastIndexOf = (array, item) ->
|
||||
return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf
|
||||
i = array.length
|
||||
while i
|
||||
if array[i] is item then return i else i--
|
||||
-1
|
||||
|
||||
|
||||
# Generate an integer Array containing an arithmetic progression. A port of
|
||||
# [the native Python **range** function](http://docs.python.org/library/functions.html#range).
|
||||
_.range = (start, stop, step) ->
|
||||
a = arguments
|
||||
solo = a.length <= 1
|
||||
i = start = if solo then 0 else a[0]
|
||||
stop = if solo then a[0] else a[1]
|
||||
step = a[2] or 1
|
||||
len = Math.ceil((stop - start) / step)
|
||||
return [] if len <= 0
|
||||
range = new Array len
|
||||
idx = 0
|
||||
loop
|
||||
return range if (if step > 0 then i - stop else stop - i) >= 0
|
||||
range[idx] = i
|
||||
idx++
|
||||
i+= step
|
||||
|
||||
|
||||
# Function Functions
|
||||
# ------------------
|
||||
|
||||
# Create a function bound to a given object (assigning `this`, and arguments,
|
||||
# optionally). Binding with arguments is also known as **curry**.
|
||||
_.bind = (func, obj) ->
|
||||
args = _.rest arguments, 2
|
||||
-> func.apply obj or root, args.concat arguments
|
||||
|
||||
|
||||
# Bind all of an object's methods to that object. Useful for ensuring that
|
||||
# all callbacks defined on an object belong to it.
|
||||
_.bindAll = (obj) ->
|
||||
funcs = if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
|
||||
_.each funcs, (f) -> obj[f] = _.bind obj[f], obj
|
||||
obj
|
||||
|
||||
|
||||
# Delays a function for the given number of milliseconds, and then calls
|
||||
# it with the arguments supplied.
|
||||
_.delay = (func, wait) ->
|
||||
args = _.rest arguments, 2
|
||||
setTimeout((-> func.apply(func, args)), wait)
|
||||
|
||||
|
||||
# Memoize an expensive function by storing its results.
|
||||
_.memoize = (func, hasher) ->
|
||||
memo = {}
|
||||
hasher or= _.identity
|
||||
->
|
||||
key = hasher.apply this, arguments
|
||||
return memo[key] if key of memo
|
||||
memo[key] = func.apply this, arguments
|
||||
|
||||
|
||||
# Defers a function, scheduling it to run after the current call stack has
|
||||
# cleared.
|
||||
_.defer = (func) ->
|
||||
_.delay.apply _, [func, 1].concat _.rest arguments
|
||||
|
||||
|
||||
# Returns the first function passed as an argument to the second,
|
||||
# allowing you to adjust arguments, run code before and after, and
|
||||
# conditionally execute the original function.
|
||||
_.wrap = (func, wrapper) ->
|
||||
-> wrapper.apply wrapper, [func].concat arguments
|
||||
|
||||
|
||||
# Returns a function that is the composition of a list of functions, each
|
||||
# consuming the return value of the function that follows.
|
||||
_.compose = ->
|
||||
funcs = arguments
|
||||
->
|
||||
args = arguments
|
||||
for i in [funcs.length - 1..0] by -1
|
||||
args = [funcs[i].apply(this, args)]
|
||||
args[0]
|
||||
|
||||
|
||||
# Object Functions
|
||||
# ----------------
|
||||
|
||||
# Retrieve the names of an object's properties.
|
||||
_.keys = nativeKeys or (obj) ->
|
||||
return _.range 0, obj.length if _.isArray(obj)
|
||||
key for key, val of obj
|
||||
|
||||
|
||||
# Retrieve the values of an object's properties.
|
||||
_.values = (obj) ->
|
||||
_.map obj, _.identity
|
||||
|
||||
|
||||
# Return a sorted list of the function names available in Underscore.
|
||||
_.functions = (obj) ->
|
||||
_.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()
|
||||
|
||||
|
||||
# Extend a given object with all of the properties in a source object.
|
||||
_.extend = (obj) ->
|
||||
for source in _.rest(arguments)
|
||||
obj[key] = val for key, val of source
|
||||
obj
|
||||
|
||||
|
||||
# Create a (shallow-cloned) duplicate of an object.
|
||||
_.clone = (obj) ->
|
||||
return obj.slice 0 if _.isArray obj
|
||||
_.extend {}, obj
|
||||
|
||||
|
||||
# Invokes interceptor with the obj, and then returns obj.
|
||||
# The primary purpose of this method is to "tap into" a method chain,
|
||||
# in order to perform operations on intermediate results within
|
||||
the chain.
|
||||
_.tap = (obj, interceptor) ->
|
||||
interceptor obj
|
||||
obj
|
||||
|
||||
|
||||
# Perform a deep comparison to check if two objects are equal.
|
||||
_.isEqual = (a, b) ->
|
||||
# Check object identity.
|
||||
return true if a is b
|
||||
# Different types?
|
||||
atype = typeof(a); btype = typeof(b)
|
||||
return false if atype isnt btype
|
||||
# Basic equality test (watch out for coercions).
|
||||
return true if `a == b`
|
||||
# One is falsy and the other truthy.
|
||||
return false if (!a and b) or (a and !b)
|
||||
# One of them implements an `isEqual()`?
|
||||
return a.isEqual(b) if a.isEqual
|
||||
# Check dates' integer values.
|
||||
return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
|
||||
# Both are NaN?
|
||||
return false if _.isNaN(a) and _.isNaN(b)
|
||||
# Compare regular expressions.
|
||||
if _.isRegExp(a) and _.isRegExp(b)
|
||||
return a.source is b.source and
|
||||
a.global is b.global and
|
||||
a.ignoreCase is b.ignoreCase and
|
||||
a.multiline is b.multiline
|
||||
# If a is not an object by this point, we can't handle it.
|
||||
return false if atype isnt 'object'
|
||||
# Check for different array lengths before comparing contents.
|
||||
return false if a.length and (a.length isnt b.length)
|
||||
# Nothing else worked, deep compare the contents.
|
||||
aKeys = _.keys(a); bKeys = _.keys(b)
|
||||
# Different object sizes?
|
||||
return false if aKeys.length isnt bKeys.length
|
||||
# Recursive comparison of contents.
|
||||
return false for key, val of a when !(key of b) or !_.isEqual(val, b[key])
|
||||
true
|
||||
|
||||
|
||||
# Is a given array or object empty?
|
||||
_.isEmpty = (obj) ->
|
||||
return obj.length is 0 if _.isArray(obj) or _.isString(obj)
|
||||
return false for own key of obj
|
||||
true
|
||||
|
||||
|
||||
# Is a given value a DOM element?
|
||||
_.isElement = (obj) -> obj and obj.nodeType is 1
|
||||
|
||||
|
||||
# Is a given value an array?
|
||||
_.isArray = nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)
|
||||
|
||||
|
||||
# Is a given variable an arguments object?
|
||||
_.isArguments = (obj) -> obj and obj.callee
|
||||
|
||||
|
||||
# Is the given value a function?
|
||||
_.isFunction = (obj) -> !!(obj and obj.constructor and obj.call and obj.apply)
|
||||
|
||||
|
||||
# Is the given value a string?
|
||||
_.isString = (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))
|
||||
|
||||
|
||||
# Is a given value a number?
|
||||
_.isNumber = (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'
|
||||
|
||||
|
||||
# Is a given value a boolean?
|
||||
_.isBoolean = (obj) -> obj is true or obj is false
|
||||
|
||||
|
||||
# Is a given value a Date?
|
||||
_.isDate = (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
|
||||
|
||||
|
||||
# Is the given value a regular expression?
|
||||
_.isRegExp = (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
|
||||
|
||||
|
||||
# Is the given value NaN -- this one is interesting. `NaN != NaN`, and
|
||||
# `isNaN(undefined) == true`, so we make sure it's a number first.
|
||||
_.isNaN = (obj) -> _.isNumber(obj) and window.isNaN(obj)
|
||||
|
||||
|
||||
# Is a given value equal to null?
|
||||
_.isNull = (obj) -> obj is null
|
||||
|
||||
|
||||
# Is a given variable undefined?
|
||||
_.isUndefined = (obj) -> typeof obj is 'undefined'
|
||||
|
||||
|
||||
# Utility Functions
|
||||
# -----------------
|
||||
|
||||
# Run Underscore.js in noConflict mode, returning the `_` variable to its
|
||||
# previous owner. Returns a reference to the Underscore object.
|
||||
_.noConflict = ->
|
||||
root._ = previousUnderscore
|
||||
this
|
||||
|
||||
|
||||
# Keep the identity function around for default iterators.
|
||||
_.identity = (value) -> value
|
||||
|
||||
|
||||
# Run a function `n` times.
|
||||
_.times = (n, iterator, context) ->
|
||||
iterator.call context, i for i in [0...n]
|
||||
|
||||
|
||||
# Break out of the middle of an iteration.
|
||||
_.breakLoop = -> throw breaker
|
||||
|
||||
|
||||
# Add your own custom functions to the Underscore object, ensuring that
|
||||
# they're correctly added to the OOP wrapper as well.
|
||||
_.mixin = (obj) ->
|
||||
for name in _.functions(obj)
|
||||
addToWrapper name, _[name] = obj[name]
|
||||
|
||||
|
||||
# Generate a unique integer id (unique within the entire client session).
|
||||
# Useful for temporary DOM ids.
|
||||
idCounter = 0
|
||||
_.uniqueId = (prefix) ->
|
||||
(prefix or '') + idCounter++
|
||||
|
||||
|
||||
# By default, Underscore uses **ERB**-style template delimiters, change the
|
||||
# following template settings to use alternative delimiters.
|
||||
_.templateSettings = {
|
||||
start: '<%'
|
||||
end: '%>'
|
||||
interpolate: /<%=(.+?)%>/g
|
||||
}
|
||||
|
||||
|
||||
# JavaScript templating a-la **ERB**, pilfered from John Resig's
|
||||
# *Secrets of the JavaScript Ninja*, page 83.
|
||||
# Single-quote fix from Rick Strahl.
|
||||
# With alterations for arbitrary delimiters, and to preserve whitespace.
|
||||
_.template = (str, data) ->
|
||||
c = _.templateSettings
|
||||
endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
|
||||
fn = new Function 'obj',
|
||||
'var p=[],print=function(){p.push.apply(p,arguments);};' +
|
||||
'with(obj||{}){p.push(\'' +
|
||||
str.replace(/\r/g, '\\r')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\t/g, '\\t')
|
||||
.replace(endMatch,"<22><><EFBFBD>")
|
||||
.split("'").join("\\'")
|
||||
.split("<22><><EFBFBD>").join("'")
|
||||
.replace(c.interpolate, "',$1,'")
|
||||
.split(c.start).join("');")
|
||||
.split(c.end).join("p.push('") +
|
||||
"');}return p.join('');"
|
||||
if data then fn(data) else fn
|
||||
|
||||
|
||||
# Aliases
|
||||
# -------
|
||||
|
||||
_.forEach = _.each
|
||||
_.foldl = _.inject = _.reduce
|
||||
_.foldr = _.reduceRight
|
||||
_.select = _.filter
|
||||
_.all = _.every
|
||||
_.any = _.some
|
||||
_.contains = _.include
|
||||
_.head = _.first
|
||||
_.tail = _.rest
|
||||
_.methods = _.functions
|
||||
|
||||
|
||||
# Setup the OOP Wrapper
|
||||
# ---------------------
|
||||
|
||||
# If Underscore is called as a function, it returns a wrapped object that
|
||||
# can be used OO-style. This wrapper holds altered versions of all the
|
||||
# underscore functions. Wrapped objects may be chained.
|
||||
wrapper = (obj) ->
|
||||
this._wrapped = obj
|
||||
this
|
||||
|
||||
|
||||
# Helper function to continue chaining intermediate results.
|
||||
result = (obj, chain) ->
|
||||
if chain then _(obj).chain() else obj
|
||||
|
||||
|
||||
# A method to easily add functions to the OOP wrapper.
|
||||
addToWrapper = (name, func) ->
|
||||
wrapper.prototype[name] = ->
|
||||
args = _.toArray arguments
|
||||
unshift.call args, this._wrapped
|
||||
result func.apply(_, args), this._chain
|
||||
|
||||
|
||||
# Add all ofthe Underscore functions to the wrapper object.
|
||||
_.mixin _
|
||||
|
||||
|
||||
# Add all mutator Array functions to the wrapper.
|
||||
_.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) ->
|
||||
method = Array.prototype[name]
|
||||
wrapper.prototype[name] = ->
|
||||
method.apply(this._wrapped, arguments)
|
||||
result(this._wrapped, this._chain)
|
||||
|
||||
|
||||
# Add all accessor Array functions to the wrapper.
|
||||
_.each ['concat', 'join', 'slice'], (name) ->
|
||||
method = Array.prototype[name]
|
||||
wrapper.prototype[name] = ->
|
||||
result(method.apply(this._wrapped, arguments), this._chain)
|
||||
|
||||
|
||||
# Start chaining a wrapped Underscore object.
|
||||
wrapper::chain = ->
|
||||
this._chain = true
|
||||
this
|
||||
|
||||
|
||||
# Extracts the result from a wrapped and chained object.
|
||||
wrapper::value = -> this._wrapped
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-coffeescript</code>.</p>
|
||||
|
||||
<p>The CoffeeScript mode was written by Jeff Pickhardt.</p>
|
||||
|
||||
</article>
|
75
src/lib/codemirror/mode/css/index.html
vendored
75
src/lib/codemirror/mode/css/index.html
vendored
@ -1,75 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: CSS mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<link rel="stylesheet" href="../../addon/hint/show-hint.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="css.js"></script>
|
||||
<script src="../../addon/hint/show-hint.js"></script>
|
||||
<script src="../../addon/hint/css-hint.js"></script>
|
||||
<style>.CodeMirror {background: #f8f8f8;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">CSS</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>CSS mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
/* Some example CSS */
|
||||
|
||||
@import url("something.css");
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 3em 6em;
|
||||
font-family: tahoma, arial, sans-serif;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#navigation a {
|
||||
font-weight: bold;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
h1:before, h2:before {
|
||||
content: "::";
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: courier, monospace;
|
||||
font-size: 80%;
|
||||
color: #418A8A;
|
||||
}
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
extraKeys: {"Ctrl-Space": "autocomplete"},
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/css</code>, <code>text/x-scss</code> (<a href="scss.html">demo</a>), <code>text/x-less</code> (<a href="less.html">demo</a>).</p>
|
||||
|
||||
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#css_*">normal</a>, <a href="../../test/index.html#verbose,css_*">verbose</a>.</p>
|
||||
|
||||
</article>
|
54
src/lib/codemirror/mode/css/less_test.js
vendored
54
src/lib/codemirror/mode/css/less_test.js
vendored
@ -1,54 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); }
|
||||
|
||||
MT("variable",
|
||||
"[variable-2 @base]: [atom #f04615];",
|
||||
"[qualifier .class] {",
|
||||
" [property width]: [variable percentage]([number 0.5]); [comment // returns `50%`]",
|
||||
" [property color]: [variable saturate]([variable-2 @base], [number 5%]);",
|
||||
"}");
|
||||
|
||||
MT("amp",
|
||||
"[qualifier .child], [qualifier .sibling] {",
|
||||
" [qualifier .parent] [atom &] {",
|
||||
" [property color]: [keyword black];",
|
||||
" }",
|
||||
" [atom &] + [atom &] {",
|
||||
" [property color]: [keyword red];",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
MT("mixin",
|
||||
"[qualifier .mixin] ([variable dark]; [variable-2 @color]) {",
|
||||
" [property color]: [atom darken]([variable-2 @color], [number 10%]);",
|
||||
"}",
|
||||
"[qualifier .mixin] ([variable light]; [variable-2 @color]) {",
|
||||
" [property color]: [atom lighten]([variable-2 @color], [number 10%]);",
|
||||
"}",
|
||||
"[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {",
|
||||
" [property display]: [atom block];",
|
||||
"}",
|
||||
"[variable-2 @switch]: [variable light];",
|
||||
"[qualifier .class] {",
|
||||
" [qualifier .mixin]([variable-2 @switch]; [atom #888]);",
|
||||
"}");
|
||||
|
||||
MT("nest",
|
||||
"[qualifier .one] {",
|
||||
" [def @media] ([property width]: [number 400px]) {",
|
||||
" [property font-size]: [number 1.2em];",
|
||||
" [def @media] [attribute print] [keyword and] [property color] {",
|
||||
" [property color]: [keyword blue];",
|
||||
" }",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
|
||||
MT("interpolation", ".@{[variable foo]} { [property font-weight]: [atom bold]; }");
|
||||
})();
|
110
src/lib/codemirror/mode/css/scss_test.js
vendored
110
src/lib/codemirror/mode/css/scss_test.js
vendored
@ -1,110 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); }
|
||||
|
||||
MT('url_with_quotation',
|
||||
"[tag foo] { [property background]:[atom url]([string test.jpg]) }");
|
||||
|
||||
MT('url_with_double_quotes',
|
||||
"[tag foo] { [property background]:[atom url]([string \"test.jpg\"]) }");
|
||||
|
||||
MT('url_with_single_quotes',
|
||||
"[tag foo] { [property background]:[atom url]([string \'test.jpg\']) }");
|
||||
|
||||
MT('string',
|
||||
"[def @import] [string \"compass/css3\"]");
|
||||
|
||||
MT('important_keyword',
|
||||
"[tag foo] { [property background]:[atom url]([string \'test.jpg\']) [keyword !important] }");
|
||||
|
||||
MT('variable',
|
||||
"[variable-2 $blue]:[atom #333]");
|
||||
|
||||
MT('variable_as_attribute',
|
||||
"[tag foo] { [property color]:[variable-2 $blue] }");
|
||||
|
||||
MT('numbers',
|
||||
"[tag foo] { [property padding]:[number 10px] [number 10] [number 10em] [number 8in] }");
|
||||
|
||||
MT('number_percentage',
|
||||
"[tag foo] { [property width]:[number 80%] }");
|
||||
|
||||
MT('selector',
|
||||
"[builtin #hello][qualifier .world]{}");
|
||||
|
||||
MT('singleline_comment',
|
||||
"[comment // this is a comment]");
|
||||
|
||||
MT('multiline_comment',
|
||||
"[comment /*foobar*/]");
|
||||
|
||||
MT('attribute_with_hyphen',
|
||||
"[tag foo] { [property font-size]:[number 10px] }");
|
||||
|
||||
MT('string_after_attribute',
|
||||
"[tag foo] { [property content]:[string \"::\"] }");
|
||||
|
||||
MT('directives',
|
||||
"[def @include] [qualifier .mixin]");
|
||||
|
||||
MT('basic_structure',
|
||||
"[tag p] { [property background]:[keyword red]; }");
|
||||
|
||||
MT('nested_structure',
|
||||
"[tag p] { [tag a] { [property color]:[keyword red]; } }");
|
||||
|
||||
MT('mixin',
|
||||
"[def @mixin] [tag table-base] {}");
|
||||
|
||||
MT('number_without_semicolon',
|
||||
"[tag p] {[property width]:[number 12]}",
|
||||
"[tag a] {[property color]:[keyword red];}");
|
||||
|
||||
MT('atom_in_nested_block',
|
||||
"[tag p] { [tag a] { [property color]:[atom #000]; } }");
|
||||
|
||||
MT('interpolation_in_property',
|
||||
"[tag foo] { #{[variable-2 $hello]}:[number 2]; }");
|
||||
|
||||
MT('interpolation_in_selector',
|
||||
"[tag foo]#{[variable-2 $hello]} { [property color]:[atom #000]; }");
|
||||
|
||||
MT('interpolation_error',
|
||||
"[tag foo]#{[variable foo]} { [property color]:[atom #000]; }");
|
||||
|
||||
MT("divide_operator",
|
||||
"[tag foo] { [property width]:[number 4] [operator /] [number 2] }");
|
||||
|
||||
MT('nested_structure_with_id_selector',
|
||||
"[tag p] { [builtin #hello] { [property color]:[keyword red]; } }");
|
||||
|
||||
MT('indent_mixin',
|
||||
"[def @mixin] [tag container] (",
|
||||
" [variable-2 $a]: [number 10],",
|
||||
" [variable-2 $b]: [number 10])",
|
||||
"{}");
|
||||
|
||||
MT('indent_nested',
|
||||
"[tag foo] {",
|
||||
" [tag bar] {",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
MT('indent_parentheses',
|
||||
"[tag foo] {",
|
||||
" [property color]: [atom darken]([variable-2 $blue],",
|
||||
" [number 9%]);",
|
||||
"}");
|
||||
|
||||
MT('indent_vardef',
|
||||
"[variable-2 $name]:",
|
||||
" [string 'val'];",
|
||||
"[tag tag] {",
|
||||
" [tag inner] {",
|
||||
" [property margin]: [number 3px];",
|
||||
" }",
|
||||
"}");
|
||||
})();
|
200
src/lib/codemirror/mode/css/test.js
vendored
200
src/lib/codemirror/mode/css/test.js
vendored
@ -1,200 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({indentUnit: 2}, "css");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
|
||||
|
||||
// Error, because "foobarhello" is neither a known type or property, but
|
||||
// property was expected (after "and"), and it should be in parentheses.
|
||||
MT("atMediaUnknownType",
|
||||
"[def @media] [attribute screen] [keyword and] [error foobarhello] { }");
|
||||
|
||||
// Soft error, because "foobarhello" is not a known property or type.
|
||||
MT("atMediaUnknownProperty",
|
||||
"[def @media] [attribute screen] [keyword and] ([error foobarhello]) { }");
|
||||
|
||||
// Make sure nesting works with media queries
|
||||
MT("atMediaMaxWidthNested",
|
||||
"[def @media] [attribute screen] [keyword and] ([property max-width]: [number 25px]) { [tag foo] { } }");
|
||||
|
||||
MT("atMediaFeatureValueKeyword",
|
||||
"[def @media] ([property orientation]: [keyword landscape]) { }");
|
||||
|
||||
MT("atMediaUnknownFeatureValueKeyword",
|
||||
"[def @media] ([property orientation]: [error upsidedown]) { }");
|
||||
|
||||
MT("tagSelector",
|
||||
"[tag foo] { }");
|
||||
|
||||
MT("classSelector",
|
||||
"[qualifier .foo-bar_hello] { }");
|
||||
|
||||
MT("idSelector",
|
||||
"[builtin #foo] { [error #foo] }");
|
||||
|
||||
MT("tagSelectorUnclosed",
|
||||
"[tag foo] { [property margin]: [number 0] } [tag bar] { }");
|
||||
|
||||
MT("tagStringNoQuotes",
|
||||
"[tag foo] { [property font-family]: [variable hello] [variable world]; }");
|
||||
|
||||
MT("tagStringDouble",
|
||||
"[tag foo] { [property font-family]: [string \"hello world\"]; }");
|
||||
|
||||
MT("tagStringSingle",
|
||||
"[tag foo] { [property font-family]: [string 'hello world']; }");
|
||||
|
||||
MT("tagColorKeyword",
|
||||
"[tag foo] {",
|
||||
" [property color]: [keyword black];",
|
||||
" [property color]: [keyword navy];",
|
||||
" [property color]: [keyword yellow];",
|
||||
"}");
|
||||
|
||||
MT("tagColorHex3",
|
||||
"[tag foo] { [property background]: [atom #fff]; }");
|
||||
|
||||
MT("tagColorHex4",
|
||||
"[tag foo] { [property background]: [atom #ffff]; }");
|
||||
|
||||
MT("tagColorHex6",
|
||||
"[tag foo] { [property background]: [atom #ffffff]; }");
|
||||
|
||||
MT("tagColorHex8",
|
||||
"[tag foo] { [property background]: [atom #ffffffff]; }");
|
||||
|
||||
MT("tagColorHex5Invalid",
|
||||
"[tag foo] { [property background]: [atom&error #fffff]; }");
|
||||
|
||||
MT("tagColorHexInvalid",
|
||||
"[tag foo] { [property background]: [atom&error #ffg]; }");
|
||||
|
||||
MT("tagNegativeNumber",
|
||||
"[tag foo] { [property margin]: [number -5px]; }");
|
||||
|
||||
MT("tagPositiveNumber",
|
||||
"[tag foo] { [property padding]: [number 5px]; }");
|
||||
|
||||
MT("tagVendor",
|
||||
"[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][atom border-box]; }");
|
||||
|
||||
MT("tagBogusProperty",
|
||||
"[tag foo] { [property&error barhelloworld]: [number 0]; }");
|
||||
|
||||
MT("tagTwoProperties",
|
||||
"[tag foo] { [property margin]: [number 0]; [property padding]: [number 0]; }");
|
||||
|
||||
MT("tagTwoPropertiesURL",
|
||||
"[tag foo] { [property background]: [atom url]([string //example.com/foo.png]); [property padding]: [number 0]; }");
|
||||
|
||||
MT("indent_tagSelector",
|
||||
"[tag strong], [tag em] {",
|
||||
" [property background]: [atom rgba](",
|
||||
" [number 255], [number 255], [number 0], [number .2]",
|
||||
" );",
|
||||
"}");
|
||||
|
||||
MT("indent_atMedia",
|
||||
"[def @media] {",
|
||||
" [tag foo] {",
|
||||
" [property color]:",
|
||||
" [keyword yellow];",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
MT("indent_comma",
|
||||
"[tag foo] {",
|
||||
" [property font-family]: [variable verdana],",
|
||||
" [atom sans-serif];",
|
||||
"}");
|
||||
|
||||
MT("indent_parentheses",
|
||||
"[tag foo]:[variable-3 before] {",
|
||||
" [property background]: [atom url](",
|
||||
"[string blahblah]",
|
||||
"[string etc]",
|
||||
"[string ]) [keyword !important];",
|
||||
"}");
|
||||
|
||||
MT("font_face",
|
||||
"[def @font-face] {",
|
||||
" [property font-family]: [string 'myfont'];",
|
||||
" [error nonsense]: [string 'abc'];",
|
||||
" [property src]: [atom url]([string http://blah]),",
|
||||
" [atom url]([string http://foo]);",
|
||||
"}");
|
||||
|
||||
MT("empty_url",
|
||||
"[def @import] [atom url]() [attribute screen];");
|
||||
|
||||
MT("parens",
|
||||
"[qualifier .foo] {",
|
||||
" [property background-image]: [variable fade]([atom #000], [number 20%]);",
|
||||
" [property border-image]: [atom linear-gradient](",
|
||||
" [atom to] [atom bottom],",
|
||||
" [variable fade]([atom #000], [number 20%]) [number 0%],",
|
||||
" [variable fade]([atom #000], [number 20%]) [number 100%]",
|
||||
" );",
|
||||
"}");
|
||||
|
||||
MT("css_variable",
|
||||
":[variable-3 root] {",
|
||||
" [variable-2 --main-color]: [atom #06c];",
|
||||
"}",
|
||||
"[tag h1][builtin #foo] {",
|
||||
" [property color]: [atom var]([variable-2 --main-color]);",
|
||||
"}");
|
||||
|
||||
MT("supports",
|
||||
"[def @supports] ([keyword not] (([property text-align-last]: [atom justify]) [keyword or] ([meta -moz-][property text-align-last]: [atom justify])) {",
|
||||
" [property text-align-last]: [atom justify];",
|
||||
"}");
|
||||
|
||||
MT("document",
|
||||
"[def @document] [tag url]([string http://blah]),",
|
||||
" [tag url-prefix]([string https://]),",
|
||||
" [tag domain]([string blah.com]),",
|
||||
" [tag regexp]([string \".*blah.+\"]) {",
|
||||
" [builtin #id] {",
|
||||
" [property background-color]: [keyword white];",
|
||||
" }",
|
||||
" [tag foo] {",
|
||||
" [property font-family]: [variable Verdana], [atom sans-serif];",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
MT("document_url",
|
||||
"[def @document] [tag url]([string http://blah]) { [qualifier .class] { } }");
|
||||
|
||||
MT("document_urlPrefix",
|
||||
"[def @document] [tag url-prefix]([string https://]) { [builtin #id] { } }");
|
||||
|
||||
MT("document_domain",
|
||||
"[def @document] [tag domain]([string blah.com]) { [tag foo] { } }");
|
||||
|
||||
MT("document_regexp",
|
||||
"[def @document] [tag regexp]([string \".*blah.+\"]) { [builtin #id] { } }");
|
||||
|
||||
MT("counter-style",
|
||||
"[def @counter-style] [variable binary] {",
|
||||
" [property system]: [atom numeric];",
|
||||
" [property symbols]: [number 0] [number 1];",
|
||||
" [property suffix]: [string \".\"];",
|
||||
" [property range]: [atom infinite];",
|
||||
" [property speak-as]: [atom numeric];",
|
||||
"}");
|
||||
|
||||
MT("counter-style-additive-symbols",
|
||||
"[def @counter-style] [variable simple-roman] {",
|
||||
" [property system]: [atom additive];",
|
||||
" [property additive-symbols]: [number 10] [variable X], [number 5] [variable V], [number 1] [variable I];",
|
||||
" [property range]: [number 1] [number 49];",
|
||||
"}");
|
||||
|
||||
MT("counter-style-use",
|
||||
"[tag ol][qualifier .roman] { [property list-style]: [variable simple-roman]; }");
|
||||
|
||||
MT("counter-style-symbols",
|
||||
"[tag ol] { [property list-style]: [atom symbols]([atom cyclic] [string \"*\"] [string \"\\2020\"] [string \"\\2021\"] [string \"\\A7\"]); }");
|
||||
})();
|
79
src/lib/codemirror/mode/haml/index.html
vendored
79
src/lib/codemirror/mode/haml/index.html
vendored
@ -1,79 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: HAML mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../xml/xml.js"></script>
|
||||
<script src="../htmlmixed/htmlmixed.js"></script>
|
||||
<script src="../javascript/javascript.js"></script>
|
||||
<script src="../ruby/ruby.js"></script>
|
||||
<script src="haml.js"></script>
|
||||
<style>.CodeMirror {background: #f8f8f8;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">HAML</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>HAML mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
!!!
|
||||
#content
|
||||
.left.column(title="title"){:href => "/hello", :test => "#{hello}_#{world}"}
|
||||
<!-- This is a comment -->
|
||||
%h2 Welcome to our site!
|
||||
%p= puts "HAML MODE"
|
||||
.right.column
|
||||
= render :partial => "sidebar"
|
||||
|
||||
.container
|
||||
.row
|
||||
.span8
|
||||
%h1.title= @page_title
|
||||
%p.title= @page_title
|
||||
%p
|
||||
/
|
||||
The same as HTML comment
|
||||
Hello multiline comment
|
||||
|
||||
-# haml comment
|
||||
This wont be displayed
|
||||
nor will this
|
||||
Date/Time:
|
||||
- now = DateTime.now
|
||||
%strong= now
|
||||
- if now > DateTime.parse("December 31, 2006")
|
||||
= "Happy new " + "year!"
|
||||
|
||||
%title
|
||||
= @title
|
||||
\= @title
|
||||
<h1>Title</h1>
|
||||
<h1 title="HELLO">
|
||||
Title
|
||||
</h1>
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
mode: "text/x-haml"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-haml</code>.</p>
|
||||
|
||||
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#haml_*">normal</a>, <a href="../../test/index.html#verbose,haml_*">verbose</a>.</p>
|
||||
|
||||
</article>
|
97
src/lib/codemirror/mode/haml/test.js
vendored
97
src/lib/codemirror/mode/haml/test.js
vendored
@ -1,97 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "haml");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
|
||||
|
||||
// Requires at least one media query
|
||||
MT("elementName",
|
||||
"[tag %h1] Hey There");
|
||||
|
||||
MT("oneElementPerLine",
|
||||
"[tag %h1] Hey There %h2");
|
||||
|
||||
MT("idSelector",
|
||||
"[tag %h1][attribute #test] Hey There");
|
||||
|
||||
MT("classSelector",
|
||||
"[tag %h1][attribute .hello] Hey There");
|
||||
|
||||
MT("docType",
|
||||
"[tag !!! XML]");
|
||||
|
||||
MT("comment",
|
||||
"[comment / Hello WORLD]");
|
||||
|
||||
MT("notComment",
|
||||
"[tag %h1] This is not a / comment ");
|
||||
|
||||
MT("attributes",
|
||||
"[tag %a]([variable title][operator =][string \"test\"]){[atom :title] [operator =>] [string \"test\"]}");
|
||||
|
||||
MT("htmlCode",
|
||||
"[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket </][tag h1][tag&bracket >]");
|
||||
|
||||
MT("rubyBlock",
|
||||
"[operator =][variable-2 @item]");
|
||||
|
||||
MT("selectorRubyBlock",
|
||||
"[tag %a.selector=] [variable-2 @item]");
|
||||
|
||||
MT("nestedRubyBlock",
|
||||
"[tag %a]",
|
||||
" [operator =][variable puts] [string \"test\"]");
|
||||
|
||||
MT("multilinePlaintext",
|
||||
"[tag %p]",
|
||||
" Hello,",
|
||||
" World");
|
||||
|
||||
MT("multilineRuby",
|
||||
"[tag %p]",
|
||||
" [comment -# this is a comment]",
|
||||
" [comment and this is a comment too]",
|
||||
" Date/Time",
|
||||
" [operator -] [variable now] [operator =] [tag DateTime][operator .][property now]",
|
||||
" [tag %strong=] [variable now]",
|
||||
" [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])",
|
||||
" [operator =][string \"Happy\"]",
|
||||
" [operator =][string \"Belated\"]",
|
||||
" [operator =][string \"Birthday\"]");
|
||||
|
||||
MT("multilineComment",
|
||||
"[comment /]",
|
||||
" [comment Multiline]",
|
||||
" [comment Comment]");
|
||||
|
||||
MT("hamlComment",
|
||||
"[comment -# this is a comment]");
|
||||
|
||||
MT("multilineHamlComment",
|
||||
"[comment -# this is a comment]",
|
||||
" [comment and this is a comment too]");
|
||||
|
||||
MT("multilineHTMLComment",
|
||||
"[comment <!--]",
|
||||
" [comment what a comment]",
|
||||
" [comment -->]");
|
||||
|
||||
MT("hamlAfterRubyTag",
|
||||
"[attribute .block]",
|
||||
" [tag %strong=] [variable now]",
|
||||
" [attribute .test]",
|
||||
" [operator =][variable now]",
|
||||
" [attribute .right]");
|
||||
|
||||
MT("stretchedRuby",
|
||||
"[operator =] [variable puts] [string \"Hello\"],",
|
||||
" [string \"World\"]");
|
||||
|
||||
MT("interpolationInHashAttribute",
|
||||
//"[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test");
|
||||
"[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test");
|
||||
|
||||
MT("interpolationInHTMLAttribute",
|
||||
"[tag %div]([variable title][operator =][string \"#{][variable test][string }_#{][variable ting]()[string }\"]) Test");
|
||||
})();
|
59
src/lib/codemirror/mode/htmlembedded/index.html
vendored
59
src/lib/codemirror/mode/htmlembedded/index.html
vendored
@ -1,59 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Html Embedded Scripts mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../xml/xml.js"></script>
|
||||
<script src="../javascript/javascript.js"></script>
|
||||
<script src="../css/css.js"></script>
|
||||
<script src="../htmlmixed/htmlmixed.js"></script>
|
||||
<script src="../../addon/mode/multiplex.js"></script>
|
||||
<script src="htmlembedded.js"></script>
|
||||
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Html Embedded Scripts</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Html Embedded Scripts mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
<%
|
||||
function hello(who) {
|
||||
return "Hello " + who;
|
||||
}
|
||||
%>
|
||||
This is an example of EJS (embedded javascript)
|
||||
<p>The program says <%= hello("world") %>.</p>
|
||||
<script>
|
||||
alert("And here is some normal JS code"); // also colored
|
||||
</script>
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
mode: "application/x-ejs",
|
||||
indentUnit: 4,
|
||||
indentWithTabs: true
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>Mode for html embedded scripts like JSP and ASP.NET. Depends on HtmlMixed which in turn depends on
|
||||
JavaScript, CSS and XML.<br />Other dependencies include those of the scripting language chosen.</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>application/x-aspx</code> (ASP.NET),
|
||||
<code>application/x-ejs</code> (Embedded Javascript), <code>application/x-jsp</code> (JavaServer Pages)</p>
|
||||
</article>
|
89
src/lib/codemirror/mode/htmlmixed/index.html
vendored
89
src/lib/codemirror/mode/htmlmixed/index.html
vendored
@ -1,89 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: HTML mixed mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/selection/selection-pointer.js"></script>
|
||||
<script src="../xml/xml.js"></script>
|
||||
<script src="../javascript/javascript.js"></script>
|
||||
<script src="../css/css.js"></script>
|
||||
<script src="../vbscript/vbscript.js"></script>
|
||||
<script src="htmlmixed.js"></script>
|
||||
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">HTML mixed</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>HTML mixed mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
<html style="color: green">
|
||||
<!-- this is a comment -->
|
||||
<head>
|
||||
<title>Mixed HTML Example</title>
|
||||
<style type="text/css">
|
||||
h1 {font-family: comic sans; color: #f0f;}
|
||||
div {background: yellow !important;}
|
||||
body {
|
||||
max-width: 50em;
|
||||
margin: 1em 2em 1em 5em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Mixed HTML Example</h1>
|
||||
<script>
|
||||
function jsFunc(arg1, arg2) {
|
||||
if (arg1 && arg2) document.body.innerHTML = "achoo";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</textarea></form>
|
||||
<script>
|
||||
// Define an extended mixed-mode that understands vbscript and
|
||||
// leaves mustache/handlebars embedded templates in html mode
|
||||
var mixedMode = {
|
||||
name: "htmlmixed",
|
||||
scriptTypes: [{matches: /\/x-handlebars-template|\/x-mustache/i,
|
||||
mode: null},
|
||||
{matches: /(text|application)\/(x-)?vb(a|script)/i,
|
||||
mode: "vbscript"}]
|
||||
};
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: mixedMode,
|
||||
selectionPointer: true
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>The HTML mixed mode depends on the XML, JavaScript, and CSS modes.</p>
|
||||
|
||||
<p>It takes an optional mode configuration
|
||||
option, <code>scriptTypes</code>, which can be used to add custom
|
||||
behavior for specific <code><script type="..."></code> tags. If
|
||||
given, it should hold an array of <code>{matches, mode}</code>
|
||||
objects, where <code>matches</code> is a string or regexp that
|
||||
matches the script type, and <code>mode</code> is
|
||||
either <code>null</code>, for script types that should stay in
|
||||
HTML mode, or a <a href="../../doc/manual.html#option_mode">mode
|
||||
spec</a> corresponding to the mode that should be used for the
|
||||
script.</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/html</code>
|
||||
(redefined, only takes effect if you load this parser after the
|
||||
XML parser).</p>
|
||||
|
||||
</article>
|
70
src/lib/codemirror/mode/jade/index.html
vendored
70
src/lib/codemirror/mode/jade/index.html
vendored
@ -1,70 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Jade Templating Mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../javascript/javascript.js"></script>
|
||||
<script src="../css/css.js"></script>
|
||||
<script src="../xml/xml.js"></script>
|
||||
<script src="../htmlmixed/htmlmixed.js"></script>
|
||||
<script src="jade.js"></script>
|
||||
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Jade Templating Mode</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Jade Templating Mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
doctype html
|
||||
html
|
||||
head
|
||||
title= "Jade Templating CodeMirror Mode Example"
|
||||
link(rel='stylesheet', href='/css/bootstrap.min.css')
|
||||
link(rel='stylesheet', href='/css/index.css')
|
||||
script(type='text/javascript', src='/js/jquery-1.9.1.min.js')
|
||||
script(type='text/javascript', src='/js/bootstrap.min.js')
|
||||
body
|
||||
div.header
|
||||
h1 Welcome to this Example
|
||||
div.spots
|
||||
if locals.spots
|
||||
each spot in spots
|
||||
div.spot.well
|
||||
div
|
||||
if spot.logo
|
||||
img.img-rounded.logo(src=spot.logo)
|
||||
else
|
||||
img.img-rounded.logo(src="img/placeholder.png")
|
||||
h3
|
||||
a(href=spot.hash) ##{spot.hash}
|
||||
if spot.title
|
||||
span.title #{spot.title}
|
||||
if spot.desc
|
||||
div #{spot.desc}
|
||||
else
|
||||
h3 There are no spots currently available.
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: {name: "jade", alignCDATA: true},
|
||||
lineNumbers: true
|
||||
});
|
||||
</script>
|
||||
<h3>The Jade Templating Mode</h3>
|
||||
<p> Created by Forbes Lindesay. Managed as part of a Brackets extension at <a href="https://github.com/ForbesLindesay/jade-brackets">https://github.com/ForbesLindesay/jade-brackets</a>.</p>
|
||||
<p><strong>MIME type defined:</strong> <code>text/x-jade</code>.</p>
|
||||
</article>
|
114
src/lib/codemirror/mode/javascript/index.html
vendored
114
src/lib/codemirror/mode/javascript/index.html
vendored
@ -1,114 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: JavaScript mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="../../addon/comment/continuecomment.js"></script>
|
||||
<script src="../../addon/comment/comment.js"></script>
|
||||
<script src="javascript.js"></script>
|
||||
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">JavaScript</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>JavaScript mode</h2>
|
||||
|
||||
|
||||
<div><textarea id="code" name="code">
|
||||
// Demo code (the actual new parser character stream implementation)
|
||||
|
||||
function StringStream(string) {
|
||||
this.pos = 0;
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
StringStream.prototype = {
|
||||
done: function() {return this.pos >= this.string.length;},
|
||||
peek: function() {return this.string.charAt(this.pos);},
|
||||
next: function() {
|
||||
if (this.pos < this.string.length)
|
||||
return this.string.charAt(this.pos++);
|
||||
},
|
||||
eat: function(match) {
|
||||
var ch = this.string.charAt(this.pos);
|
||||
if (typeof match == "string") var ok = ch == match;
|
||||
else var ok = ch && match.test ? match.test(ch) : match(ch);
|
||||
if (ok) {this.pos++; return ch;}
|
||||
},
|
||||
eatWhile: function(match) {
|
||||
var start = this.pos;
|
||||
while (this.eat(match));
|
||||
if (this.pos > start) return this.string.slice(start, this.pos);
|
||||
},
|
||||
backUp: function(n) {this.pos -= n;},
|
||||
column: function() {return this.pos;},
|
||||
eatSpace: function() {
|
||||
var start = this.pos;
|
||||
while (/\s/.test(this.string.charAt(this.pos))) this.pos++;
|
||||
return this.pos - start;
|
||||
},
|
||||
match: function(pattern, consume, caseInsensitive) {
|
||||
if (typeof pattern == "string") {
|
||||
function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
|
||||
if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
|
||||
if (consume !== false) this.pos += str.length;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var match = this.string.slice(this.pos).match(pattern);
|
||||
if (match && consume !== false) this.pos += match[0].length;
|
||||
return match;
|
||||
}
|
||||
}
|
||||
};
|
||||
</textarea></div>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
continueComments: "Enter",
|
||||
extraKeys: {"Ctrl-Q": "toggleComment"}
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>
|
||||
JavaScript mode supports several configuration options:
|
||||
<ul>
|
||||
<li><code>json</code> which will set the mode to expect JSON
|
||||
data rather than a JavaScript program.</li>
|
||||
<li><code>jsonld</code> which will set the mode to expect
|
||||
<a href="http://json-ld.org">JSON-LD</a> linked data rather
|
||||
than a JavaScript program (<a href="json-ld.html">demo</a>).</li>
|
||||
<li><code>typescript</code> which will activate additional
|
||||
syntax highlighting and some other things for TypeScript code
|
||||
(<a href="typescript.html">demo</a>).</li>
|
||||
<li><code>statementIndent</code> which (given a number) will
|
||||
determine the amount of indentation to use for statements
|
||||
continued on a new line.</li>
|
||||
<li><code>wordCharacters</code>, a regexp that indicates which
|
||||
characters should be considered part of an identifier.
|
||||
Defaults to <code>/[\w$]/</code>, which does not handle
|
||||
non-ASCII identifiers. Can be set to something more elaborate
|
||||
to improve Unicode support.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/javascript</code>, <code>application/json</code>, <code>application/ld+json</code>, <code>text/typescript</code>, <code>application/typescript</code>.</p>
|
||||
</article>
|
210
src/lib/codemirror/mode/javascript/test.js
vendored
210
src/lib/codemirror/mode/javascript/test.js
vendored
@ -1,210 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({indentUnit: 2}, "javascript");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
|
||||
|
||||
MT("locals",
|
||||
"[keyword function] [def foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }");
|
||||
|
||||
MT("comma-and-binop",
|
||||
"[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }");
|
||||
|
||||
MT("destructuring",
|
||||
"([keyword function]([def a], [[[def b], [def c] ]]) {",
|
||||
" [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);",
|
||||
" [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];",
|
||||
"})();");
|
||||
|
||||
MT("destructure_trailing_comma",
|
||||
"[keyword let] {[def a], [def b],} [operator =] [variable foo];",
|
||||
"[keyword let] [def c];"); // Parser still in good state?
|
||||
|
||||
MT("class_body",
|
||||
"[keyword class] [def Foo] {",
|
||||
" [property constructor]() {}",
|
||||
" [property sayName]() {",
|
||||
" [keyword return] [string-2 `foo${][variable foo][string-2 }oo`];",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
MT("class",
|
||||
"[keyword class] [def Point] [keyword extends] [variable SuperThing] {",
|
||||
" [property get] [property prop]() { [keyword return] [number 24]; }",
|
||||
" [property constructor]([def x], [def y]) {",
|
||||
" [keyword super]([string 'something']);",
|
||||
" [keyword this].[property x] [operator =] [variable-2 x];",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
MT("import",
|
||||
"[keyword function] [def foo]() {",
|
||||
" [keyword import] [def $] [keyword from] [string 'jquery'];",
|
||||
" [keyword import] { [def encrypt], [def decrypt] } [keyword from] [string 'crypto'];",
|
||||
"}");
|
||||
|
||||
MT("const",
|
||||
"[keyword function] [def f]() {",
|
||||
" [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];",
|
||||
"}");
|
||||
|
||||
MT("for/of",
|
||||
"[keyword for]([keyword let] [def of] [keyword of] [variable something]) {}");
|
||||
|
||||
MT("generator",
|
||||
"[keyword function*] [def repeat]([def n]) {",
|
||||
" [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])",
|
||||
" [keyword yield] [variable-2 i];",
|
||||
"}");
|
||||
|
||||
MT("quotedStringAddition",
|
||||
"[keyword let] [def f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];");
|
||||
|
||||
MT("quotedFatArrow",
|
||||
"[keyword let] [def f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c];");
|
||||
|
||||
MT("fatArrow",
|
||||
"[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);",
|
||||
"[variable a];", // No longer in scope
|
||||
"[keyword let] [def f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];",
|
||||
"[variable c];");
|
||||
|
||||
MT("spread",
|
||||
"[keyword function] [def f]([def a], [meta ...][def b]) {",
|
||||
" [variable something]([variable-2 a], [meta ...][variable-2 b]);",
|
||||
"}");
|
||||
|
||||
MT("comprehension",
|
||||
"[keyword function] [def f]() {",
|
||||
" [[([variable x] [operator +] [number 1]) [keyword for] ([keyword var] [def x] [keyword in] [variable y]) [keyword if] [variable pred]([variable-2 x]) ]];",
|
||||
" ([variable u] [keyword for] ([keyword var] [def u] [keyword of] [variable generateValues]()) [keyword if] ([variable-2 u].[property color] [operator ===] [string 'blue']));",
|
||||
"}");
|
||||
|
||||
MT("quasi",
|
||||
"[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");
|
||||
|
||||
MT("quasi_no_function",
|
||||
"[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");
|
||||
|
||||
MT("indent_statement",
|
||||
"[keyword var] [def x] [operator =] [number 10]",
|
||||
"[variable x] [operator +=] [variable y] [operator +]",
|
||||
" [atom Infinity]",
|
||||
"[keyword debugger];");
|
||||
|
||||
MT("indent_if",
|
||||
"[keyword if] ([number 1])",
|
||||
" [keyword break];",
|
||||
"[keyword else] [keyword if] ([number 2])",
|
||||
" [keyword continue];",
|
||||
"[keyword else]",
|
||||
" [number 10];",
|
||||
"[keyword if] ([number 1]) {",
|
||||
" [keyword break];",
|
||||
"} [keyword else] [keyword if] ([number 2]) {",
|
||||
" [keyword continue];",
|
||||
"} [keyword else] {",
|
||||
" [number 10];",
|
||||
"}");
|
||||
|
||||
MT("indent_for",
|
||||
"[keyword for] ([keyword var] [def i] [operator =] [number 0];",
|
||||
" [variable i] [operator <] [number 100];",
|
||||
" [variable i][operator ++])",
|
||||
" [variable doSomething]([variable i]);",
|
||||
"[keyword debugger];");
|
||||
|
||||
MT("indent_c_style",
|
||||
"[keyword function] [def foo]()",
|
||||
"{",
|
||||
" [keyword debugger];",
|
||||
"}");
|
||||
|
||||
MT("indent_else",
|
||||
"[keyword for] (;;)",
|
||||
" [keyword if] ([variable foo])",
|
||||
" [keyword if] ([variable bar])",
|
||||
" [number 1];",
|
||||
" [keyword else]",
|
||||
" [number 2];",
|
||||
" [keyword else]",
|
||||
" [number 3];");
|
||||
|
||||
MT("indent_funarg",
|
||||
"[variable foo]([number 10000],",
|
||||
" [keyword function]([def a]) {",
|
||||
" [keyword debugger];",
|
||||
"};");
|
||||
|
||||
MT("indent_below_if",
|
||||
"[keyword for] (;;)",
|
||||
" [keyword if] ([variable foo])",
|
||||
" [number 1];",
|
||||
"[number 2];");
|
||||
|
||||
MT("multilinestring",
|
||||
"[keyword var] [def x] [operator =] [string 'foo\\]",
|
||||
"[string bar'];");
|
||||
|
||||
MT("scary_regexp",
|
||||
"[string-2 /foo[[/]]bar/];");
|
||||
|
||||
MT("indent_strange_array",
|
||||
"[keyword var] [def x] [operator =] [[",
|
||||
" [number 1],,",
|
||||
" [number 2],",
|
||||
"]];",
|
||||
"[number 10];");
|
||||
|
||||
MT("param_default",
|
||||
"[keyword function] [def foo]([def x] [operator =] [string-2 `foo${][number 10][string-2 }bar`]) {",
|
||||
" [keyword return] [variable-2 x];",
|
||||
"}");
|
||||
|
||||
MT("new_target",
|
||||
"[keyword function] [def F]([def target]) {",
|
||||
" [keyword if] ([variable-2 target] [operator &&] [keyword new].[keyword target].[property name]) {",
|
||||
" [keyword return] [keyword new]",
|
||||
" .[keyword target];",
|
||||
" }",
|
||||
"}");
|
||||
|
||||
var jsonld_mode = CodeMirror.getMode(
|
||||
{indentUnit: 2},
|
||||
{name: "javascript", jsonld: true}
|
||||
);
|
||||
function LD(name) {
|
||||
test.mode(name, jsonld_mode, Array.prototype.slice.call(arguments, 1));
|
||||
}
|
||||
|
||||
LD("json_ld_keywords",
|
||||
'{',
|
||||
' [meta "@context"]: {',
|
||||
' [meta "@base"]: [string "http://example.com"],',
|
||||
' [meta "@vocab"]: [string "http://xmlns.com/foaf/0.1/"],',
|
||||
' [property "likesFlavor"]: {',
|
||||
' [meta "@container"]: [meta "@list"]',
|
||||
' [meta "@reverse"]: [string "@beFavoriteOf"]',
|
||||
' },',
|
||||
' [property "nick"]: { [meta "@container"]: [meta "@set"] },',
|
||||
' [property "nick"]: { [meta "@container"]: [meta "@index"] }',
|
||||
' },',
|
||||
' [meta "@graph"]: [[ {',
|
||||
' [meta "@id"]: [string "http://dbpedia.org/resource/John_Lennon"],',
|
||||
' [property "name"]: [string "John Lennon"],',
|
||||
' [property "modified"]: {',
|
||||
' [meta "@value"]: [string "2010-05-29T14:17:39+02:00"],',
|
||||
' [meta "@type"]: [string "http://www.w3.org/2001/XMLSchema#dateTime"]',
|
||||
' }',
|
||||
' } ]]',
|
||||
'}');
|
||||
|
||||
LD("json_ld_fake",
|
||||
'{',
|
||||
' [property "@fake"]: [string "@fake"],',
|
||||
' [property "@contextual"]: [string "@identifier"],',
|
||||
' [property "user@domain.com"]: [string "@graphical"],',
|
||||
' [property "@ID"]: [string "@@ID"]',
|
||||
'}');
|
||||
})();
|
797
src/lib/codemirror/mode/markdown/markdown.js
vendored
Normal file
797
src/lib/codemirror/mode/markdown/markdown.js
vendored
Normal file
@ -0,0 +1,797 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror", "../xml/xml", "../meta"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
|
||||
var htmlMode = CodeMirror.getMode(cmCfg, "text/html");
|
||||
var htmlModeMissing = htmlMode.name == "null"
|
||||
|
||||
function getMode(name) {
|
||||
if (CodeMirror.findModeByName) {
|
||||
var found = CodeMirror.findModeByName(name);
|
||||
if (found) name = found.mime || found.mimes[0];
|
||||
}
|
||||
var mode = CodeMirror.getMode(cmCfg, name);
|
||||
return mode.name == "null" ? null : mode;
|
||||
}
|
||||
|
||||
// Should characters that affect highlighting be highlighted separate?
|
||||
// Does not include characters that will be output (such as `1.` and `-` for lists)
|
||||
if (modeCfg.highlightFormatting === undefined)
|
||||
modeCfg.highlightFormatting = false;
|
||||
|
||||
// Maximum number of nested blockquotes. Set to 0 for infinite nesting.
|
||||
// Excess `>` will emit `error` token.
|
||||
if (modeCfg.maxBlockquoteDepth === undefined)
|
||||
modeCfg.maxBlockquoteDepth = 0;
|
||||
|
||||
// Should underscores in words open/close em/strong?
|
||||
if (modeCfg.underscoresBreakWords === undefined)
|
||||
modeCfg.underscoresBreakWords = true;
|
||||
|
||||
// Use `fencedCodeBlocks` to configure fenced code blocks. false to
|
||||
// disable, string to specify a precise regexp that the fence should
|
||||
// match, and true to allow three or more backticks or tildes (as
|
||||
// per CommonMark).
|
||||
|
||||
// Turn on task lists? ("- [ ] " and "- [x] ")
|
||||
if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
|
||||
|
||||
// Turn on strikethrough syntax
|
||||
if (modeCfg.strikethrough === undefined)
|
||||
modeCfg.strikethrough = false;
|
||||
|
||||
// Allow token types to be overridden by user-provided token types.
|
||||
if (modeCfg.tokenTypeOverrides === undefined)
|
||||
modeCfg.tokenTypeOverrides = {};
|
||||
|
||||
var tokenTypes = {
|
||||
header: "header",
|
||||
code: "comment",
|
||||
quote: "quote",
|
||||
list1: "variable-2",
|
||||
list2: "variable-3",
|
||||
list3: "keyword",
|
||||
hr: "hr",
|
||||
image: "tag",
|
||||
formatting: "formatting",
|
||||
linkInline: "link",
|
||||
linkEmail: "link",
|
||||
linkText: "link",
|
||||
linkHref: "string",
|
||||
em: "em",
|
||||
strong: "strong",
|
||||
strikethrough: "strikethrough"
|
||||
};
|
||||
|
||||
for (var tokenType in tokenTypes) {
|
||||
if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) {
|
||||
tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType];
|
||||
}
|
||||
}
|
||||
|
||||
var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/
|
||||
, ulRE = /^[*\-+]\s+/
|
||||
, olRE = /^[0-9]+([.)])\s+/
|
||||
, taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
|
||||
, atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/
|
||||
, setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/
|
||||
, textRE = /^[^#!\[\]*_\\<>` "'(~]+/
|
||||
, fencedCodeRE = new RegExp("^(" + (modeCfg.fencedCodeBlocks === true ? "~~~+|```+" : modeCfg.fencedCodeBlocks) +
|
||||
")[ \\t]*([\\w+#\-]*)");
|
||||
|
||||
function switchInline(stream, state, f) {
|
||||
state.f = state.inline = f;
|
||||
return f(stream, state);
|
||||
}
|
||||
|
||||
function switchBlock(stream, state, f) {
|
||||
state.f = state.block = f;
|
||||
return f(stream, state);
|
||||
}
|
||||
|
||||
function lineIsEmpty(line) {
|
||||
return !line || !/\S/.test(line.string)
|
||||
}
|
||||
|
||||
// Blocks
|
||||
|
||||
function blankLine(state) {
|
||||
// Reset linkTitle state
|
||||
state.linkTitle = false;
|
||||
// Reset EM state
|
||||
state.em = false;
|
||||
// Reset STRONG state
|
||||
state.strong = false;
|
||||
// Reset strikethrough state
|
||||
state.strikethrough = false;
|
||||
// Reset state.quote
|
||||
state.quote = 0;
|
||||
// Reset state.indentedCode
|
||||
state.indentedCode = false;
|
||||
if (htmlModeMissing && state.f == htmlBlock) {
|
||||
state.f = inlineNormal;
|
||||
state.block = blockNormal;
|
||||
}
|
||||
// Reset state.trailingSpace
|
||||
state.trailingSpace = 0;
|
||||
state.trailingSpaceNewLine = false;
|
||||
// Mark this line as blank
|
||||
state.prevLine = state.thisLine
|
||||
state.thisLine = null
|
||||
return null;
|
||||
}
|
||||
|
||||
function blockNormal(stream, state) {
|
||||
|
||||
var sol = stream.sol();
|
||||
|
||||
var prevLineIsList = state.list !== false,
|
||||
prevLineIsIndentedCode = state.indentedCode;
|
||||
|
||||
state.indentedCode = false;
|
||||
|
||||
if (prevLineIsList) {
|
||||
if (state.indentationDiff >= 0) { // Continued list
|
||||
if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
|
||||
state.indentation -= state.indentationDiff;
|
||||
}
|
||||
state.list = null;
|
||||
} else if (state.indentation > 0) {
|
||||
state.list = null;
|
||||
} else { // No longer a list
|
||||
state.list = false;
|
||||
}
|
||||
}
|
||||
|
||||
var match = null;
|
||||
if (state.indentationDiff >= 4) {
|
||||
stream.skipToEnd();
|
||||
if (prevLineIsIndentedCode || lineIsEmpty(state.prevLine)) {
|
||||
state.indentation -= 4;
|
||||
state.indentedCode = true;
|
||||
return tokenTypes.code;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (stream.eatSpace()) {
|
||||
return null;
|
||||
} else if ((match = stream.match(atxHeaderRE)) && match[1].length <= 6) {
|
||||
state.header = match[1].length;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "header";
|
||||
state.f = state.inline;
|
||||
return getType(state);
|
||||
} else if (!lineIsEmpty(state.prevLine) && !state.quote && !prevLineIsList &&
|
||||
!prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) {
|
||||
state.header = match[0].charAt(0) == '=' ? 1 : 2;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "header";
|
||||
state.f = state.inline;
|
||||
return getType(state);
|
||||
} else if (stream.eat('>')) {
|
||||
state.quote = sol ? 1 : state.quote + 1;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "quote";
|
||||
stream.eatSpace();
|
||||
return getType(state);
|
||||
} else if (stream.peek() === '[') {
|
||||
return switchInline(stream, state, footnoteLink);
|
||||
} else if (stream.match(hrRE, true)) {
|
||||
state.hr = true;
|
||||
return tokenTypes.hr;
|
||||
} else if ((lineIsEmpty(state.prevLine) || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
|
||||
var listType = null;
|
||||
if (stream.match(ulRE, true)) {
|
||||
listType = 'ul';
|
||||
} else {
|
||||
stream.match(olRE, true);
|
||||
listType = 'ol';
|
||||
}
|
||||
state.indentation = stream.column() + stream.current().length;
|
||||
state.list = true;
|
||||
|
||||
// While this list item's marker's indentation
|
||||
// is less than the deepest list item's content's indentation,
|
||||
// pop the deepest list item indentation off the stack.
|
||||
while (state.listStack && stream.column() < state.listStack[state.listStack.length - 1]) {
|
||||
state.listStack.pop();
|
||||
}
|
||||
|
||||
// Add this list item's content's indentation to the stack
|
||||
state.listStack.push(state.indentation);
|
||||
|
||||
if (modeCfg.taskLists && stream.match(taskListRE, false)) {
|
||||
state.taskList = true;
|
||||
}
|
||||
state.f = state.inline;
|
||||
if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
|
||||
return getType(state);
|
||||
} else if (modeCfg.fencedCodeBlocks && (match = stream.match(fencedCodeRE, true))) {
|
||||
state.fencedChars = match[1]
|
||||
// try switching mode
|
||||
state.localMode = getMode(match[2]);
|
||||
if (state.localMode) state.localState = CodeMirror.startState(state.localMode);
|
||||
state.f = state.block = local;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "code-block";
|
||||
state.code = -1
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
return switchInline(stream, state, state.inline);
|
||||
}
|
||||
|
||||
function htmlBlock(stream, state) {
|
||||
var style = htmlMode.token(stream, state.htmlState);
|
||||
if (!htmlModeMissing) {
|
||||
var inner = CodeMirror.innerMode(htmlMode, state.htmlState)
|
||||
if ((inner.mode.name == "xml" && inner.state.tagStart === null &&
|
||||
(!inner.state.context && inner.state.tokenize.isInText)) ||
|
||||
(state.md_inside && stream.current().indexOf(">") > -1)) {
|
||||
state.f = inlineNormal;
|
||||
state.block = blockNormal;
|
||||
state.htmlState = null;
|
||||
}
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
function local(stream, state) {
|
||||
if (state.fencedChars && stream.match(state.fencedChars, false)) {
|
||||
state.localMode = state.localState = null;
|
||||
state.f = state.block = leavingLocal;
|
||||
return null;
|
||||
} else if (state.localMode) {
|
||||
return state.localMode.token(stream, state.localState);
|
||||
} else {
|
||||
stream.skipToEnd();
|
||||
return tokenTypes.code;
|
||||
}
|
||||
}
|
||||
|
||||
function leavingLocal(stream, state) {
|
||||
stream.match(state.fencedChars);
|
||||
state.block = blockNormal;
|
||||
state.f = inlineNormal;
|
||||
state.fencedChars = null;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "code-block";
|
||||
state.code = 1
|
||||
var returnType = getType(state);
|
||||
state.code = 0
|
||||
return returnType;
|
||||
}
|
||||
|
||||
// Inline
|
||||
function getType(state) {
|
||||
var styles = [];
|
||||
|
||||
if (state.formatting) {
|
||||
styles.push(tokenTypes.formatting);
|
||||
|
||||
if (typeof state.formatting === "string") state.formatting = [state.formatting];
|
||||
|
||||
for (var i = 0; i < state.formatting.length; i++) {
|
||||
styles.push(tokenTypes.formatting + "-" + state.formatting[i]);
|
||||
|
||||
if (state.formatting[i] === "header") {
|
||||
styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header);
|
||||
}
|
||||
|
||||
// Add `formatting-quote` and `formatting-quote-#` for blockquotes
|
||||
// Add `error` instead if the maximum blockquote nesting depth is passed
|
||||
if (state.formatting[i] === "quote") {
|
||||
if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
|
||||
styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote);
|
||||
} else {
|
||||
styles.push("error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state.taskOpen) {
|
||||
styles.push("meta");
|
||||
return styles.length ? styles.join(' ') : null;
|
||||
}
|
||||
if (state.taskClosed) {
|
||||
styles.push("property");
|
||||
return styles.length ? styles.join(' ') : null;
|
||||
}
|
||||
|
||||
if (state.linkHref) {
|
||||
styles.push(tokenTypes.linkHref, "url");
|
||||
} else { // Only apply inline styles to non-url text
|
||||
if (state.strong) { styles.push(tokenTypes.strong); }
|
||||
if (state.em) { styles.push(tokenTypes.em); }
|
||||
if (state.strikethrough) { styles.push(tokenTypes.strikethrough); }
|
||||
if (state.linkText) { styles.push(tokenTypes.linkText); }
|
||||
if (state.code) { styles.push(tokenTypes.code); }
|
||||
}
|
||||
|
||||
if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); }
|
||||
|
||||
if (state.quote) {
|
||||
styles.push(tokenTypes.quote);
|
||||
|
||||
// Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
|
||||
if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
|
||||
styles.push(tokenTypes.quote + "-" + state.quote);
|
||||
} else {
|
||||
styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.list !== false) {
|
||||
var listMod = (state.listStack.length - 1) % 3;
|
||||
if (!listMod) {
|
||||
styles.push(tokenTypes.list1);
|
||||
} else if (listMod === 1) {
|
||||
styles.push(tokenTypes.list2);
|
||||
} else {
|
||||
styles.push(tokenTypes.list3);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.trailingSpaceNewLine) {
|
||||
styles.push("trailing-space-new-line");
|
||||
} else if (state.trailingSpace) {
|
||||
styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
|
||||
}
|
||||
|
||||
return styles.length ? styles.join(' ') : null;
|
||||
}
|
||||
|
||||
function handleText(stream, state) {
|
||||
if (stream.match(textRE, true)) {
|
||||
return getType(state);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function inlineNormal(stream, state) {
|
||||
var style = state.text(stream, state);
|
||||
if (typeof style !== 'undefined')
|
||||
return style;
|
||||
|
||||
if (state.list) { // List marker (*, +, -, 1., etc)
|
||||
state.list = null;
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
if (state.taskList) {
|
||||
var taskOpen = stream.match(taskListRE, true)[1] !== "x";
|
||||
if (taskOpen) state.taskOpen = true;
|
||||
else state.taskClosed = true;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "task";
|
||||
state.taskList = false;
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
state.taskOpen = false;
|
||||
state.taskClosed = false;
|
||||
|
||||
if (state.header && stream.match(/^#+$/, true)) {
|
||||
if (modeCfg.highlightFormatting) state.formatting = "header";
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
// Get sol() value now, before character is consumed
|
||||
var sol = stream.sol();
|
||||
|
||||
var ch = stream.next();
|
||||
|
||||
// Matches link titles present on next line
|
||||
if (state.linkTitle) {
|
||||
state.linkTitle = false;
|
||||
var matchCh = ch;
|
||||
if (ch === '(') {
|
||||
matchCh = ')';
|
||||
}
|
||||
matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
|
||||
var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
|
||||
if (stream.match(new RegExp(regex), true)) {
|
||||
return tokenTypes.linkHref;
|
||||
}
|
||||
}
|
||||
|
||||
// If this block is changed, it may need to be updated in GFM mode
|
||||
if (ch === '`') {
|
||||
var previousFormatting = state.formatting;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "code";
|
||||
stream.eatWhile('`');
|
||||
var count = stream.current().length
|
||||
if (state.code == 0) {
|
||||
state.code = count
|
||||
return getType(state)
|
||||
} else if (count == state.code) { // Must be exact
|
||||
var t = getType(state)
|
||||
state.code = 0
|
||||
return t
|
||||
} else {
|
||||
state.formatting = previousFormatting
|
||||
return getType(state)
|
||||
}
|
||||
} else if (state.code) {
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
if (ch === '\\') {
|
||||
stream.next();
|
||||
if (modeCfg.highlightFormatting) {
|
||||
var type = getType(state);
|
||||
var formattingEscape = tokenTypes.formatting + "-escape";
|
||||
return type ? type + " " + formattingEscape : formattingEscape;
|
||||
}
|
||||
}
|
||||
|
||||
if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
|
||||
stream.match(/\[[^\]]*\]/);
|
||||
state.inline = state.f = linkHref;
|
||||
return tokenTypes.image;
|
||||
}
|
||||
|
||||
if (ch === '[' && stream.match(/[^\]]*\](\(.*\)| ?\[.*?\])/, false)) {
|
||||
state.linkText = true;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
if (ch === ']' && state.linkText && stream.match(/\(.*?\)| ?\[.*?\]/, false)) {
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||
var type = getType(state);
|
||||
state.linkText = false;
|
||||
state.inline = state.f = linkHref;
|
||||
return type;
|
||||
}
|
||||
|
||||
if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
|
||||
state.f = state.inline = linkInline;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||
var type = getType(state);
|
||||
if (type){
|
||||
type += " ";
|
||||
} else {
|
||||
type = "";
|
||||
}
|
||||
return type + tokenTypes.linkInline;
|
||||
}
|
||||
|
||||
if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
|
||||
state.f = state.inline = linkInline;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||
var type = getType(state);
|
||||
if (type){
|
||||
type += " ";
|
||||
} else {
|
||||
type = "";
|
||||
}
|
||||
return type + tokenTypes.linkEmail;
|
||||
}
|
||||
|
||||
if (ch === '<' && stream.match(/^(!--|\w)/, false)) {
|
||||
var end = stream.string.indexOf(">", stream.pos);
|
||||
if (end != -1) {
|
||||
var atts = stream.string.substring(stream.start, end);
|
||||
if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true;
|
||||
}
|
||||
stream.backUp(1);
|
||||
state.htmlState = CodeMirror.startState(htmlMode);
|
||||
return switchBlock(stream, state, htmlBlock);
|
||||
}
|
||||
|
||||
if (ch === '<' && stream.match(/^\/\w*?>/)) {
|
||||
state.md_inside = false;
|
||||
return "tag";
|
||||
}
|
||||
|
||||
var ignoreUnderscore = false;
|
||||
if (!modeCfg.underscoresBreakWords) {
|
||||
if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) {
|
||||
var prevPos = stream.pos - 2;
|
||||
if (prevPos >= 0) {
|
||||
var prevCh = stream.string.charAt(prevPos);
|
||||
if (prevCh !== '_' && prevCh.match(/(\w)/, false)) {
|
||||
ignoreUnderscore = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
|
||||
if (sol && stream.peek() === ' ') {
|
||||
// Do nothing, surrounded by newline and space
|
||||
} else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG
|
||||
if (modeCfg.highlightFormatting) state.formatting = "strong";
|
||||
var t = getType(state);
|
||||
state.strong = false;
|
||||
return t;
|
||||
} else if (!state.strong && stream.eat(ch)) { // Add STRONG
|
||||
state.strong = ch;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "strong";
|
||||
return getType(state);
|
||||
} else if (state.em === ch) { // Remove EM
|
||||
if (modeCfg.highlightFormatting) state.formatting = "em";
|
||||
var t = getType(state);
|
||||
state.em = false;
|
||||
return t;
|
||||
} else if (!state.em) { // Add EM
|
||||
state.em = ch;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "em";
|
||||
return getType(state);
|
||||
}
|
||||
} else if (ch === ' ') {
|
||||
if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
|
||||
if (stream.peek() === ' ') { // Surrounded by spaces, ignore
|
||||
return getType(state);
|
||||
} else { // Not surrounded by spaces, back up pointer
|
||||
stream.backUp(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (modeCfg.strikethrough) {
|
||||
if (ch === '~' && stream.eatWhile(ch)) {
|
||||
if (state.strikethrough) {// Remove strikethrough
|
||||
if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
|
||||
var t = getType(state);
|
||||
state.strikethrough = false;
|
||||
return t;
|
||||
} else if (stream.match(/^[^\s]/, false)) {// Add strikethrough
|
||||
state.strikethrough = true;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
|
||||
return getType(state);
|
||||
}
|
||||
} else if (ch === ' ') {
|
||||
if (stream.match(/^~~/, true)) { // Probably surrounded by space
|
||||
if (stream.peek() === ' ') { // Surrounded by spaces, ignore
|
||||
return getType(state);
|
||||
} else { // Not surrounded by spaces, back up pointer
|
||||
stream.backUp(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ch === ' ') {
|
||||
if (stream.match(/ +$/, false)) {
|
||||
state.trailingSpace++;
|
||||
} else if (state.trailingSpace) {
|
||||
state.trailingSpaceNewLine = true;
|
||||
}
|
||||
}
|
||||
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
function linkInline(stream, state) {
|
||||
var ch = stream.next();
|
||||
|
||||
if (ch === ">") {
|
||||
state.f = state.inline = inlineNormal;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||
var type = getType(state);
|
||||
if (type){
|
||||
type += " ";
|
||||
} else {
|
||||
type = "";
|
||||
}
|
||||
return type + tokenTypes.linkInline;
|
||||
}
|
||||
|
||||
stream.match(/^[^>]+/, true);
|
||||
|
||||
return tokenTypes.linkInline;
|
||||
}
|
||||
|
||||
function linkHref(stream, state) {
|
||||
// Check if space, and return NULL if so (to avoid marking the space)
|
||||
if(stream.eatSpace()){
|
||||
return null;
|
||||
}
|
||||
var ch = stream.next();
|
||||
if (ch === '(' || ch === '[') {
|
||||
state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]", 0);
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link-string";
|
||||
state.linkHref = true;
|
||||
return getType(state);
|
||||
}
|
||||
return 'error';
|
||||
}
|
||||
|
||||
var linkRE = {
|
||||
")": /^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/,
|
||||
"]": /^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\\]]|\\.)*\])*?(?=\])/
|
||||
}
|
||||
|
||||
function getLinkHrefInside(endChar) {
|
||||
return function(stream, state) {
|
||||
var ch = stream.next();
|
||||
|
||||
if (ch === endChar) {
|
||||
state.f = state.inline = inlineNormal;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link-string";
|
||||
var returnState = getType(state);
|
||||
state.linkHref = false;
|
||||
return returnState;
|
||||
}
|
||||
|
||||
stream.match(linkRE[endChar])
|
||||
state.linkHref = true;
|
||||
return getType(state);
|
||||
};
|
||||
}
|
||||
|
||||
function footnoteLink(stream, state) {
|
||||
if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) {
|
||||
state.f = footnoteLinkInside;
|
||||
stream.next(); // Consume [
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||
state.linkText = true;
|
||||
return getType(state);
|
||||
}
|
||||
return switchInline(stream, state, inlineNormal);
|
||||
}
|
||||
|
||||
function footnoteLinkInside(stream, state) {
|
||||
if (stream.match(/^\]:/, true)) {
|
||||
state.f = state.inline = footnoteUrl;
|
||||
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||
var returnType = getType(state);
|
||||
state.linkText = false;
|
||||
return returnType;
|
||||
}
|
||||
|
||||
stream.match(/^([^\]\\]|\\.)+/, true);
|
||||
|
||||
return tokenTypes.linkText;
|
||||
}
|
||||
|
||||
function footnoteUrl(stream, state) {
|
||||
// Check if space, and return NULL if so (to avoid marking the space)
|
||||
if(stream.eatSpace()){
|
||||
return null;
|
||||
}
|
||||
// Match URL
|
||||
stream.match(/^[^\s]+/, true);
|
||||
// Check for link title
|
||||
if (stream.peek() === undefined) { // End of line, set flag to check next line
|
||||
state.linkTitle = true;
|
||||
} else { // More content on line, check if link title
|
||||
stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
|
||||
}
|
||||
state.f = state.inline = inlineNormal;
|
||||
return tokenTypes.linkHref + " url";
|
||||
}
|
||||
|
||||
var mode = {
|
||||
startState: function() {
|
||||
return {
|
||||
f: blockNormal,
|
||||
|
||||
prevLine: null,
|
||||
thisLine: null,
|
||||
|
||||
block: blockNormal,
|
||||
htmlState: null,
|
||||
indentation: 0,
|
||||
|
||||
inline: inlineNormal,
|
||||
text: handleText,
|
||||
|
||||
formatting: false,
|
||||
linkText: false,
|
||||
linkHref: false,
|
||||
linkTitle: false,
|
||||
code: 0,
|
||||
em: false,
|
||||
strong: false,
|
||||
header: 0,
|
||||
hr: false,
|
||||
taskList: false,
|
||||
list: false,
|
||||
listStack: [],
|
||||
quote: 0,
|
||||
trailingSpace: 0,
|
||||
trailingSpaceNewLine: false,
|
||||
strikethrough: false,
|
||||
fencedChars: null
|
||||
};
|
||||
},
|
||||
|
||||
copyState: function(s) {
|
||||
return {
|
||||
f: s.f,
|
||||
|
||||
prevLine: s.prevLine,
|
||||
thisLine: s.thisLine,
|
||||
|
||||
block: s.block,
|
||||
htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
|
||||
indentation: s.indentation,
|
||||
|
||||
localMode: s.localMode,
|
||||
localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,
|
||||
|
||||
inline: s.inline,
|
||||
text: s.text,
|
||||
formatting: false,
|
||||
linkTitle: s.linkTitle,
|
||||
code: s.code,
|
||||
em: s.em,
|
||||
strong: s.strong,
|
||||
strikethrough: s.strikethrough,
|
||||
header: s.header,
|
||||
hr: s.hr,
|
||||
taskList: s.taskList,
|
||||
list: s.list,
|
||||
listStack: s.listStack.slice(0),
|
||||
quote: s.quote,
|
||||
indentedCode: s.indentedCode,
|
||||
trailingSpace: s.trailingSpace,
|
||||
trailingSpaceNewLine: s.trailingSpaceNewLine,
|
||||
md_inside: s.md_inside,
|
||||
fencedChars: s.fencedChars
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
|
||||
// Reset state.formatting
|
||||
state.formatting = false;
|
||||
|
||||
if (stream != state.thisLine) {
|
||||
var forceBlankLine = state.header || state.hr;
|
||||
|
||||
// Reset state.header and state.hr
|
||||
state.header = 0;
|
||||
state.hr = false;
|
||||
|
||||
if (stream.match(/^\s*$/, true) || forceBlankLine) {
|
||||
blankLine(state);
|
||||
if (!forceBlankLine) return null
|
||||
state.prevLine = null
|
||||
}
|
||||
|
||||
state.prevLine = state.thisLine
|
||||
state.thisLine = stream
|
||||
|
||||
// Reset state.taskList
|
||||
state.taskList = false;
|
||||
|
||||
// Reset state.trailingSpace
|
||||
state.trailingSpace = 0;
|
||||
state.trailingSpaceNewLine = false;
|
||||
|
||||
state.f = state.block;
|
||||
var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length;
|
||||
state.indentationDiff = Math.min(indentation - state.indentation, 4);
|
||||
state.indentation = state.indentation + state.indentationDiff;
|
||||
if (indentation > 0) return null;
|
||||
}
|
||||
return state.f(stream, state);
|
||||
},
|
||||
|
||||
innerMode: function(state) {
|
||||
if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
|
||||
if (state.localState) return {state: state.localState, mode: state.localMode};
|
||||
return {state: state, mode: mode};
|
||||
},
|
||||
|
||||
blankLine: blankLine,
|
||||
|
||||
getType: getType,
|
||||
|
||||
fold: "markdown"
|
||||
};
|
||||
return mode;
|
||||
}, "xml");
|
||||
|
||||
CodeMirror.defineMIME("text/x-markdown", "markdown");
|
||||
|
||||
});
|
66
src/lib/codemirror/mode/sass/index.html
vendored
66
src/lib/codemirror/mode/sass/index.html
vendored
@ -1,66 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Sass mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="sass.js"></script>
|
||||
<style>.CodeMirror {border: 1px solid #ddd; font-size:12px; height: 400px}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Sass</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Sass mode</h2>
|
||||
<form><textarea id="code" name="code">// Variable Definitions
|
||||
|
||||
$page-width: 800px
|
||||
$sidebar-width: 200px
|
||||
$primary-color: #eeeeee
|
||||
|
||||
// Global Attributes
|
||||
|
||||
body
|
||||
font:
|
||||
family: sans-serif
|
||||
size: 30em
|
||||
weight: bold
|
||||
|
||||
// Scoped Styles
|
||||
|
||||
#contents
|
||||
width: $page-width
|
||||
#sidebar
|
||||
float: right
|
||||
width: $sidebar-width
|
||||
#main
|
||||
width: $page-width - $sidebar-width
|
||||
background: $primary-color
|
||||
h2
|
||||
color: blue
|
||||
|
||||
#footer
|
||||
height: 200px
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers : true,
|
||||
matchBrackets : true
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-sass</code>.</p>
|
||||
</article>
|
61
src/lib/codemirror/mode/xml/index.html
vendored
61
src/lib/codemirror/mode/xml/index.html
vendored
@ -1,61 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: XML mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="xml.js"></script>
|
||||
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">XML</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>XML mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
<html style="color: green">
|
||||
<!-- this is a comment -->
|
||||
<head>
|
||||
<title>HTML Example</title>
|
||||
</head>
|
||||
<body>
|
||||
The indentation tries to be <em>somewhat &quot;do what
|
||||
I mean&quot;</em>... but might not match your style.
|
||||
</body>
|
||||
</html>
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: "text/html",
|
||||
lineNumbers: true
|
||||
});
|
||||
</script>
|
||||
<p>The XML mode supports these configuration parameters:</p>
|
||||
<dl>
|
||||
<dt><code>htmlMode (boolean)</code></dt>
|
||||
<dd>This switches the mode to parse HTML instead of XML. This
|
||||
means attributes do not have to be quoted, and some elements
|
||||
(such as <code>br</code>) do not require a closing tag.</dd>
|
||||
<dt><code>matchClosing (boolean)</code></dt>
|
||||
<dd>Controls whether the mode checks that close tags match the
|
||||
corresponding opening tag, and highlights mismatches as errors.
|
||||
Defaults to true.</dd>
|
||||
<dt><code>alignCDATA (boolean)</code></dt>
|
||||
<dd>Setting this to true will force the opening tag of CDATA
|
||||
blocks to not be indented.</dd>
|
||||
</dl>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>application/xml</code>, <code>text/html</code>.</p>
|
||||
</article>
|
51
src/lib/codemirror/mode/xml/test.js
vendored
51
src/lib/codemirror/mode/xml/test.js
vendored
@ -1,51 +0,0 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml";
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); }
|
||||
|
||||
MT("matching",
|
||||
"[tag&bracket <][tag top][tag&bracket >]",
|
||||
" text",
|
||||
" [tag&bracket <][tag inner][tag&bracket />]",
|
||||
"[tag&bracket </][tag top][tag&bracket >]");
|
||||
|
||||
MT("nonmatching",
|
||||
"[tag&bracket <][tag top][tag&bracket >]",
|
||||
" [tag&bracket <][tag inner][tag&bracket />]",
|
||||
" [tag&bracket </][tag&error tip][tag&bracket&error >]");
|
||||
|
||||
MT("doctype",
|
||||
"[meta <!doctype foobar>]",
|
||||
"[tag&bracket <][tag top][tag&bracket />]");
|
||||
|
||||
MT("cdata",
|
||||
"[tag&bracket <][tag top][tag&bracket >]",
|
||||
" [atom <![CDATA[foo]",
|
||||
"[atom barbazguh]]]]>]",
|
||||
"[tag&bracket </][tag top][tag&bracket >]");
|
||||
|
||||
// HTML tests
|
||||
mode = CodeMirror.getMode({indentUnit: 2}, "text/html");
|
||||
|
||||
MT("selfclose",
|
||||
"[tag&bracket <][tag html][tag&bracket >]",
|
||||
" [tag&bracket <][tag link] [attribute rel]=[string stylesheet] [attribute href]=[string \"/foobar\"][tag&bracket >]",
|
||||
"[tag&bracket </][tag html][tag&bracket >]");
|
||||
|
||||
MT("list",
|
||||
"[tag&bracket <][tag ol][tag&bracket >]",
|
||||
" [tag&bracket <][tag li][tag&bracket >]one",
|
||||
" [tag&bracket <][tag li][tag&bracket >]two",
|
||||
"[tag&bracket </][tag ol][tag&bracket >]");
|
||||
|
||||
MT("valueless",
|
||||
"[tag&bracket <][tag input] [attribute type]=[string checkbox] [attribute checked][tag&bracket />]");
|
||||
|
||||
MT("pThenArticle",
|
||||
"[tag&bracket <][tag p][tag&bracket >]",
|
||||
" foo",
|
||||
"[tag&bracket <][tag article][tag&bracket >]bar");
|
||||
|
||||
})();
|
12
src/lib/coffee-script.js
Normal file
12
src/lib/coffee-script.js
Normal file
File diff suppressed because one or more lines are too long
9
src/lib/jade.js
Normal file
9
src/lib/jade.js
Normal file
File diff suppressed because one or more lines are too long
23
src/lib/less.min.js
vendored
Normal file
23
src/lib/less.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1285
src/lib/marked.js
Normal file
1285
src/lib/marked.js
Normal file
File diff suppressed because it is too large
Load Diff
202
src/lib/sass.js
Normal file
202
src/lib/sass.js
Normal file
@ -0,0 +1,202 @@
|
||||
/*! sass.js - v0.9.10 (9a781bf) - built 2016-04-24
|
||||
providing libsass 3.3.6 (3ae9a20)
|
||||
via emscripten 1.36.1 (d5085ed)
|
||||
*/
|
||||
|
||||
(function (root, factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define([], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
root.Sass = factory();
|
||||
}
|
||||
}(this, function () {/*global document*/
|
||||
// identify the path sass.js is located at in case we're loaded by a simple
|
||||
// <script src="path/to/sass.js"></script>
|
||||
// this path can be used to identify the location of
|
||||
// * sass.worker.js from sass.js
|
||||
// * libsass.js.mem from sass.sync.js
|
||||
// see https://github.com/medialize/sass.js/pull/32#issuecomment-103142214
|
||||
// see https://github.com/medialize/sass.js/issues/33
|
||||
var SASSJS_RELATIVE_PATH = (function() {
|
||||
'use strict';
|
||||
|
||||
// in Node things are rather simple
|
||||
if (typeof __dirname !== 'undefined') {
|
||||
return __dirname;
|
||||
}
|
||||
|
||||
// we can only run this test in the browser,
|
||||
// so make sure we actually have a DOM to work with.
|
||||
if (typeof document === 'undefined' || !document.getElementsByTagName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// http://www.2ality.com/2014/05/current-script.html
|
||||
var currentScript = document.currentScript || (function() {
|
||||
var scripts = document.getElementsByTagName('script');
|
||||
return scripts[scripts.length - 1];
|
||||
})();
|
||||
|
||||
var path = currentScript && currentScript.src;
|
||||
if (!path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// [worker] make sure we're not running in some concatenated thing
|
||||
if (path.slice(-8) === '/sass.js') {
|
||||
return path.slice(0, -8);
|
||||
}
|
||||
|
||||
// [sync] make sure we're not running in some concatenated thing
|
||||
if (path.slice(-13) === '/sass.sync.js') {
|
||||
return path.slice(0, -13);
|
||||
}
|
||||
|
||||
return null;
|
||||
})() || '.';
|
||||
|
||||
/*global Worker, SASSJS_RELATIVE_PATH*/
|
||||
'use strict';
|
||||
|
||||
var noop = function(){};
|
||||
var slice = [].slice;
|
||||
// defined upon first Sass.initialize() call
|
||||
var globalWorkerUrl;
|
||||
|
||||
function Sass(workerUrl) {
|
||||
if (!workerUrl && !globalWorkerUrl) {
|
||||
/*jshint laxbreak:true */
|
||||
throw new Error(
|
||||
'Sass needs to be initialized with the URL of sass.worker.js - '
|
||||
+ 'either via Sass.setWorkerUrl(url) or by new Sass(url)'
|
||||
);
|
||||
/*jshint laxbreak:false */
|
||||
}
|
||||
|
||||
if (!globalWorkerUrl) {
|
||||
globalWorkerUrl = workerUrl;
|
||||
}
|
||||
|
||||
// bind all functions
|
||||
// we're doing this because we used to have a single hard-wired instance that allowed
|
||||
// [].map(Sass.removeFile) and we need to maintain that for now (at least until 1.0.0)
|
||||
for (var key in this) {
|
||||
if (typeof this[key] === 'function') {
|
||||
this[key] = this[key].bind(this);
|
||||
}
|
||||
}
|
||||
|
||||
this._callbacks = {};
|
||||
this._worker = new Worker(workerUrl || globalWorkerUrl);
|
||||
this._worker.addEventListener('message', this._handleWorkerMessage, false);
|
||||
}
|
||||
|
||||
// allow setting the workerUrl before the first Sass instance is initialized,
|
||||
// where registering the global workerUrl would've happened automatically
|
||||
Sass.setWorkerUrl = function(workerUrl) {
|
||||
globalWorkerUrl = workerUrl;
|
||||
};
|
||||
|
||||
Sass.style = {
|
||||
nested: 0,
|
||||
expanded: 1,
|
||||
compact: 2,
|
||||
compressed: 3
|
||||
};
|
||||
|
||||
Sass.comments = {
|
||||
'none': 0,
|
||||
'default': 1
|
||||
};
|
||||
|
||||
Sass.prototype = {
|
||||
style: Sass.style,
|
||||
comments: Sass.comments,
|
||||
|
||||
destroy: function() {
|
||||
this._worker && this._worker.terminate();
|
||||
this._worker = null;
|
||||
this._callbacks = {};
|
||||
this._importer = null;
|
||||
},
|
||||
|
||||
_handleWorkerMessage: function(event) {
|
||||
if (event.data.command) {
|
||||
this[event.data.command](event.data.args);
|
||||
}
|
||||
|
||||
this._callbacks[event.data.id] && this._callbacks[event.data.id](event.data.result);
|
||||
delete this._callbacks[event.data.id];
|
||||
},
|
||||
|
||||
_dispatch: function(options, callback) {
|
||||
if (!this._worker) {
|
||||
throw new Error('Sass worker has been terminated');
|
||||
}
|
||||
|
||||
options.id = 'cb' + Date.now() + Math.random();
|
||||
this._callbacks[options.id] = callback;
|
||||
this._worker.postMessage(options);
|
||||
},
|
||||
|
||||
_importerInit: function(args) {
|
||||
// importer API done callback pushing results
|
||||
// back to the worker
|
||||
var done = function done(result) {
|
||||
this._worker.postMessage({
|
||||
command: '_importerFinish',
|
||||
args: [result]
|
||||
});
|
||||
}.bind(this);
|
||||
|
||||
try {
|
||||
this._importer(args[0], done);
|
||||
} catch(e) {
|
||||
done({ error: e.message });
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
importer: function(importerCallback, callback) {
|
||||
if (typeof importerCallback !== 'function' && importerCallback !== null) {
|
||||
throw new Error('importer callback must either be a function or null');
|
||||
}
|
||||
|
||||
// callback is executed in the main EventLoop
|
||||
this._importer = importerCallback;
|
||||
// tell worker to activate importer callback
|
||||
this._worker.postMessage({
|
||||
command: 'importer',
|
||||
args: [Boolean(importerCallback)]
|
||||
});
|
||||
|
||||
callback && callback();
|
||||
},
|
||||
};
|
||||
|
||||
var commands = 'writeFile readFile listFiles removeFile clearFiles lazyFiles preloadFiles options compile compileFile';
|
||||
commands.split(' ').forEach(function(command) {
|
||||
Sass.prototype[command] = function() {
|
||||
var callback = slice.call(arguments, -1)[0];
|
||||
var args = slice.call(arguments, 0, -1);
|
||||
if (typeof callback !== 'function') {
|
||||
args.push(callback);
|
||||
callback = noop;
|
||||
}
|
||||
|
||||
this._dispatch({
|
||||
command: command,
|
||||
args: args
|
||||
}, callback);
|
||||
};
|
||||
});
|
||||
|
||||
// automatically set the workerUrl in case we're loaded by a simple
|
||||
// <script src="path/to/sass.js"></script>
|
||||
// see https://github.com/medialize/sass.js/pull/32#issuecomment-103142214
|
||||
Sass.setWorkerUrl(SASSJS_RELATIVE_PATH + '/sass.worker.js');
|
||||
return Sass;
|
||||
}));
|
813
src/lib/sass.worker.js
Normal file
813
src/lib/sass.worker.js
Normal file
File diff suppressed because one or more lines are too long
16
src/loader.js
Normal file
16
src/loader.js
Normal file
@ -0,0 +1,16 @@
|
||||
(function(w) {
|
||||
|
||||
window.loadJS = function(src) {
|
||||
var d = deferred();
|
||||
var ref = w.document.getElementsByTagName("script")[0];
|
||||
var script = w.document.createElement("script");
|
||||
script.src = src;
|
||||
script.async = true;
|
||||
ref.parentNode.insertBefore(script, ref);
|
||||
script.onload = function () {
|
||||
d.resolve();
|
||||
};
|
||||
return d.promise;
|
||||
};
|
||||
|
||||
})(window);
|
@ -8,6 +8,7 @@
|
||||
"storage",
|
||||
"tabs"
|
||||
],
|
||||
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
|
||||
"options_ui": {
|
||||
"page": "options.html",
|
||||
"chrome_style": true
|
||||
|
248
src/script.js
248
src/script.js
@ -5,13 +5,44 @@
|
||||
var editur = window.editur || {};
|
||||
var version = '1.6.0';
|
||||
|
||||
var $ = document.querySelector.bind(document);
|
||||
var $all = document.querySelectorAll.bind(document);
|
||||
window.$ = document.querySelector.bind(document);
|
||||
window.$all = document.querySelectorAll.bind(document);
|
||||
|
||||
var HtmlModes = {
|
||||
HTML: 'html',
|
||||
MARKDOWN: 'markdown',
|
||||
JADE: 'jade' // unsafe eval is put in manifest for this file
|
||||
};
|
||||
var CssModes = {
|
||||
CSS: 'css',
|
||||
SCSS: 'scss',
|
||||
LESS: 'less'
|
||||
};
|
||||
var JsModes = {
|
||||
JS: 'js',
|
||||
ES6: 'es6',
|
||||
COFFEESCRIPT: 'coffee'
|
||||
};
|
||||
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[JsModes.JS] = { label: 'JS', cmMode: 'javascript', codepenVal: 'none' };
|
||||
modes[JsModes.COFFEESCRIPT] = { label: 'CoffeeScript', cmMode: 'coffeescript', codepenVal: 'coffeescript' };
|
||||
modes[JsModes.ES6] = { label: 'ES6 (Babel)', cmMode: 'javascript', codepenVal: 'babel' };
|
||||
modes[CssModes.CSS] = { label: 'CSS', cmMode: 'css', codepenVal: 'none' };
|
||||
modes[CssModes.SCSS] = { label: 'SCSS', cmMode: 'sass', codepenVal: 'scss' };
|
||||
modes[CssModes.LESS] = { label: 'LESS', cmMode: 'text/x-less', codepenVal: 'less' };
|
||||
|
||||
var updateTimer
|
||||
, updateDelay = 500
|
||||
, currentLayoutMode
|
||||
, hasSeenNotifications = true
|
||||
, htmlMode = HtmlModes.HTML
|
||||
, jsMode = JsModes.JS
|
||||
, cssMode = CssModes.CSS
|
||||
, sass
|
||||
|
||||
, frame = $('#demo-frame')
|
||||
, htmlCode = $('#js-html-code')
|
||||
, cssCode = $('#js-css-code')
|
||||
@ -27,6 +58,9 @@
|
||||
, settingsBtn = $('#js-settings-btn')
|
||||
, notificationsBtn = $('#js-notifications-btn')
|
||||
, notificationsModal = $('#js-notifications-modal')
|
||||
, htmlModelLabel = $('#js-html-mode-label')
|
||||
, cssModelLabel = $('#js-css-mode-label')
|
||||
, jsModelLabel = $('#js-js-mode-label')
|
||||
;
|
||||
|
||||
editur.cm = {};
|
||||
@ -59,10 +93,14 @@
|
||||
$('#js-demo-side').setAttribute('style', '');
|
||||
|
||||
Split(['#js-html-code', '#js-css-code', '#js-js-code'], {
|
||||
direction: (currentLayoutMode === 2 ? 'horizontal' : 'vertical')
|
||||
direction: (currentLayoutMode === 2 ? 'horizontal' : 'vertical'),
|
||||
minSize: 34,
|
||||
gutterSize: 6
|
||||
});
|
||||
Split(['#js-code-side', '#js-demo-side' ], {
|
||||
direction: (currentLayoutMode === 2 ? 'vertical' : 'horizontal')
|
||||
direction: (currentLayoutMode === 2 ? 'vertical' : 'horizontal'),
|
||||
minSize: 34,
|
||||
gutterSize: 6
|
||||
});
|
||||
}
|
||||
function toggleLayout(mode) {
|
||||
@ -95,26 +133,124 @@
|
||||
saveSetting('code', code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loaded the code comiler based on the mode selected
|
||||
*/
|
||||
function handleModeRequirements(mode) {
|
||||
// Exit if already loaded
|
||||
if (modes[mode].hasLoaded) { return; }
|
||||
|
||||
function setLoadedFlag() {
|
||||
modes[mode].hasLoaded = true;
|
||||
}
|
||||
|
||||
if (mode === HtmlModes.JADE) {
|
||||
loadJS('lib/jade.js').then(setLoadedFlag);
|
||||
} else if (mode === HtmlModes.MARKDOWN) {
|
||||
loadJS('lib/marked.js').then(setLoadedFlag);
|
||||
} else if (mode === CssModes.LESS) {
|
||||
loadJS('lib/less.min.js').then(setLoadedFlag);
|
||||
} else if (mode === CssModes.SCSS) {
|
||||
loadJS('lib/sass.js').then(function () {
|
||||
sass = new Sass('lib/sass.worker.js');
|
||||
setLoadedFlag();
|
||||
});
|
||||
} else if (mode === JsModes.COFFEESCRIPT) {
|
||||
loadJS('lib/coffee-script.js').then(setLoadedFlag);
|
||||
} else if (mode === JsModes.ES6) {
|
||||
loadJS('lib/babel.min.js').then(setLoadedFlag);
|
||||
}
|
||||
}
|
||||
|
||||
function updateHtmlMode(value) {
|
||||
htmlMode = value;
|
||||
htmlModelLabel.textContent = modes[value].label;
|
||||
handleModeRequirements(value);
|
||||
CodeMirror.autoLoadMode(editur.cm.html, modes[value].cmMode);
|
||||
chrome.storage.sync.set({
|
||||
htmlMode: value
|
||||
}, function () {});
|
||||
}
|
||||
function updateCssMode(value) {
|
||||
cssMode = value;
|
||||
cssModelLabel.textContent = modes[value].label;
|
||||
handleModeRequirements(value);
|
||||
CodeMirror.autoLoadMode(editur.cm.css, modes[value].cmMode);
|
||||
chrome.storage.sync.set({
|
||||
cssMode: value
|
||||
}, function () {});
|
||||
}
|
||||
function updateJsMode(value) {
|
||||
jsMode = value;
|
||||
jsModelLabel.textContent = modes[value].label;
|
||||
handleModeRequirements(value);
|
||||
CodeMirror.autoLoadMode(editur.cm.js, modes[value].cmMode);
|
||||
chrome.storage.sync.set({
|
||||
jsMode: value
|
||||
}, function () {});
|
||||
}
|
||||
|
||||
// computeHtml, computeCss & computeJs evaluate the final code according
|
||||
// to whatever mode is selected and resolve the returned promise with the code.
|
||||
function computeHtml() {
|
||||
var d = deferred();
|
||||
var code = editur.cm.html.getValue();
|
||||
if (htmlMode === HtmlModes.HTML) {
|
||||
d.resolve(code);
|
||||
} else if (htmlMode === HtmlModes.MARKDOWN) {
|
||||
d.resolve(marked(code));
|
||||
} else if (htmlMode === HtmlModes.JADE) {
|
||||
d.resolve(jade.render(code));
|
||||
}
|
||||
|
||||
return d.promise;
|
||||
}
|
||||
function computeCss() {
|
||||
var d = deferred();
|
||||
var code = editur.cm.css.getValue();
|
||||
if (cssMode === CssModes.CSS) {
|
||||
d.resolve(code);
|
||||
} else if (cssMode === CssModes.SCSS) {
|
||||
sass.compile(code, function(result) {
|
||||
d.resolve(result.text);
|
||||
});
|
||||
} else if (cssMode === CssModes.LESS) {
|
||||
less.render(code).then(function (result) {
|
||||
d.resolve(result.css);
|
||||
});
|
||||
}
|
||||
|
||||
return d.promise;
|
||||
}
|
||||
function computeJs() {
|
||||
var d = deferred();
|
||||
var code = editur.cm.js.getValue();
|
||||
if (jsMode === JsModes.JS) {
|
||||
d.resolve(code);
|
||||
} else if (jsMode === JsModes.COFFEESCRIPT) {
|
||||
d.resolve(CoffeeScript.compile(code, { bare: true }));
|
||||
} else if (jsMode === JsModes.ES6) {
|
||||
d.resolve(Babel.transform(editur.cm.js.getValue(), { presets: ['es2015'] }).code);
|
||||
}
|
||||
|
||||
return d.promise;
|
||||
}
|
||||
|
||||
window.onunload = function () {
|
||||
saveCode();
|
||||
};
|
||||
|
||||
editur.setPreviewContent = function () {
|
||||
var html = editur.cm.html.getValue();
|
||||
var css = editur.cm.css.getValue();
|
||||
var js = editur.cm.js.getValue();
|
||||
|
||||
|
||||
html = '<html>\n<head>\n<style>\n' + css + '\n</style>\n</head>\n<body>\n' + html + '\n<script>\n' + js + '\n</script></body>\n</html>';
|
||||
function createPreviewFile(html, css, js) {
|
||||
var contents = '<html>\n<head>\n<style>\n' + css + '\n</style>\n</head>\n<body>\n' + html + '\n<script>\n' + js + '\n</script></body>\n</html>';
|
||||
|
||||
var fileWritten = false;
|
||||
|
||||
var blob = new Blob([ html ], {type: "text/plain;charset=UTF-8"});
|
||||
var blob = new Blob([ contents ], { type: "text/plain;charset=UTF-8" });
|
||||
|
||||
function errorHandler() { console.log(arguments); }
|
||||
|
||||
window.webkitRequestFileSystem(window.TEMPORARY, 1024 * 1024 * 5, function(fs){
|
||||
fs.root.getFile('preview.html', {create: true}, function(fileEntry) {
|
||||
fs.root.getFile('preview.html', { create: true }, function(fileEntry) {
|
||||
fileEntry.createWriter(function(fileWriter) {
|
||||
function onWriteComplete() {
|
||||
if (fileWritten) {
|
||||
@ -131,29 +267,43 @@
|
||||
}, errorHandler);
|
||||
}, errorHandler);
|
||||
}, errorHandler);
|
||||
}
|
||||
|
||||
editur.setPreviewContent = function () {
|
||||
var htmlPromise = computeHtml();
|
||||
var cssPromise = computeCss();
|
||||
var jsPromise = computeJs();
|
||||
Promise.all([htmlPromise, cssPromise, jsPromise]).then(function (result) {
|
||||
createPreviewFile(result[0], result[1], result[2]);
|
||||
});
|
||||
};
|
||||
|
||||
function saveFile() {
|
||||
var html = editur.cm.html.getValue();
|
||||
var css = editur.cm.css.getValue();
|
||||
var js = editur.cm.js.getValue();
|
||||
var htmlPromise = computeHtml();
|
||||
var cssPromise = computeCss();
|
||||
var jsPromise = computeJs();
|
||||
Promise.all([htmlPromise, cssPromise, jsPromise]).then(function (result) {
|
||||
var html = result[0],
|
||||
css = result[1],
|
||||
js = result[2];
|
||||
|
||||
var fileContent = '<html><head>\n<style>\n'
|
||||
+ css + '\n</style>\n</head>\n<body>\n'
|
||||
+ html + '\n<script>\n' + js + '\n</script>\n\n</body>\n</html>';
|
||||
var fileContent = '<html><head>\n<style>\n'
|
||||
+ css + '\n</style>\n</head>\n<body>\n'
|
||||
+ html + '\n<script>\n' + js + '\n</script>\n\n</body>\n</html>';
|
||||
|
||||
var d = new Date();
|
||||
var fileName = [ 'web-maker', d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds() ].join('-');
|
||||
fileName += '.html';
|
||||
var d = new Date();
|
||||
var fileName = [ 'web-maker', d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds() ].join('-');
|
||||
fileName += '.html';
|
||||
|
||||
var a = document.createElement('a');
|
||||
var blob = new Blob([ fileContent ], {type: "text/html;charset=UTF-8"});
|
||||
a.href = window.URL.createObjectURL(blob);
|
||||
a.download = fileName;
|
||||
a.style.display = 'none';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
var a = document.createElement('a');
|
||||
var blob = new Blob([ fileContent ], { type: "text/html;charset=UTF-8" });
|
||||
a.href = window.URL.createObjectURL(blob);
|
||||
a.download = fileName;
|
||||
a.style.display = 'none';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
a.remove();
|
||||
});
|
||||
}
|
||||
|
||||
function initEditor(element, options) {
|
||||
@ -194,6 +344,8 @@
|
||||
function init () {
|
||||
var lastCode;
|
||||
|
||||
CodeMirror.modeURL = "lib/codemirror/mode/%N/%N.js";
|
||||
|
||||
layoutBtn1.addEventListener('click', function () { saveSetting('layoutMode', 1); toggleLayout(1); return false; });
|
||||
layoutBtn2.addEventListener('click', function () { saveSetting('layoutMode', 2); toggleLayout(2); return false; });
|
||||
layoutBtn3.addEventListener('click', function () { saveSetting('layoutMode', 3); toggleLayout(3); return false; });
|
||||
@ -220,7 +372,14 @@
|
||||
title: 'A Web Maker experiment',
|
||||
html: editur.cm.html.getValue(),
|
||||
css: editur.cm.css.getValue(),
|
||||
js: editur.cm.js.getValue()
|
||||
js: editur.cm.js.getValue(),
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
html_pre_processor: modes[htmlMode].codepenVal,
|
||||
css_pre_processor: modes[cssMode].codepenVal,
|
||||
js_pre_processor: modes[jsMode].codepenVal
|
||||
|
||||
/* eslint-enable camelcase */
|
||||
};
|
||||
json = JSON.stringify(json)
|
||||
.replace(/"/g, """)
|
||||
@ -234,6 +393,25 @@
|
||||
saveFile();
|
||||
});
|
||||
|
||||
// Attach listeners on mode change menu items
|
||||
var modeItems = [].slice.call($all('.js-modes-menu a'));
|
||||
modeItems.forEach(function (item) {
|
||||
item.addEventListener('click', function (e) {
|
||||
var mode = e.currentTarget.dataset.mode;
|
||||
var type = e.currentTarget.dataset.type;
|
||||
var currentMode = type === 'html' ? htmlMode : (type === 'css' ? cssMode : jsMode);
|
||||
if (currentMode !== mode) {
|
||||
if (type === 'html') {
|
||||
updateHtmlMode(mode);
|
||||
} else if (type === 'js') {
|
||||
updateJsMode(mode);
|
||||
} else if (type === 'css') {
|
||||
updateCssMode(mode);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('keydown', function (event) {
|
||||
if ((event.ctrlKey || event.metaKey) && (event.keyCode === 83)){
|
||||
event.preventDefault();
|
||||
@ -277,7 +455,10 @@
|
||||
|
||||
// Get synced `preserveLastCode` setting to get back last code (or not).
|
||||
chrome.storage.sync.get({
|
||||
preserveLastCode: true
|
||||
preserveLastCode: true,
|
||||
htmlMode: 'html',
|
||||
jsMode: 'js',
|
||||
cssMode: 'css'
|
||||
}, function syncGetCallback(result) {
|
||||
if (result.preserveLastCode && lastCode) {
|
||||
editur.cm.html.setValue(lastCode.html);
|
||||
@ -287,6 +468,9 @@
|
||||
editur.cm.css.refresh();
|
||||
editur.cm.js.refresh();
|
||||
}
|
||||
updateHtmlMode(result.htmlMode);
|
||||
updateJsMode(result.jsMode);
|
||||
updateCssMode(result.cssMode);
|
||||
});
|
||||
|
||||
// Check for new version notifications
|
||||
|
Loading…
x
Reference in New Issue
Block a user