yann300
10 years ago
64 changed files with 11690 additions and 1421 deletions
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,114 +0,0 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file autoprovider.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Marian Oancea <marian@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
/* |
|||
* @brief if qt object is available, uses QtProvider, |
|||
* if not tries to connect over websockets |
|||
* if it fails, it uses HttpRpcProvider |
|||
*/ |
|||
|
|||
var web3 = require('./web3'); // jshint ignore:line
|
|||
if (process.env.NODE_ENV !== 'build') { |
|||
var WebSocket = require('ws'); // jshint ignore:line
|
|||
} |
|||
|
|||
/** |
|||
* AutoProvider object prototype is implementing 'provider protocol' |
|||
* Automatically tries to setup correct provider(Qt, WebSockets or HttpRpc) |
|||
* First it checkes if we are ethereum browser (if navigator.qt object is available) |
|||
* if yes, we are using QtProvider |
|||
* if no, we check if it is possible to establish websockets connection with ethereum (ws://localhost:40404/eth is default)
|
|||
* if it's not possible, we are using httprpc provider (http://localhost:8080)
|
|||
* The constructor allows you to specify uris on which we are trying to connect over http or websockets |
|||
* You can do that by passing objects with fields httrpc and websockets |
|||
*/ |
|||
var AutoProvider = function (userOptions) { |
|||
if (web3.haveProvider()) { |
|||
return; |
|||
} |
|||
|
|||
// before we determine what provider we are, we have to cache request
|
|||
this.sendQueue = []; |
|||
this.onmessageQueue = []; |
|||
|
|||
if (navigator.qt) { |
|||
this.provider = new web3.providers.QtProvider(); |
|||
return; |
|||
} |
|||
|
|||
userOptions = userOptions || {}; |
|||
var options = { |
|||
httprpc: userOptions.httprpc || 'http://localhost:8080', |
|||
websockets: userOptions.websockets || 'ws://localhost:40404/eth' |
|||
}; |
|||
|
|||
var self = this; |
|||
var closeWithSuccess = function (success) { |
|||
ws.close(); |
|||
if (success) { |
|||
self.provider = new web3.providers.WebSocketProvider(options.websockets); |
|||
} else { |
|||
self.provider = new web3.providers.HttpRpcProvider(options.httprpc); |
|||
self.poll = self.provider.poll.bind(self.provider); |
|||
} |
|||
self.sendQueue.forEach(function (payload) { |
|||
self.provider.send(payload); |
|||
}); |
|||
self.onmessageQueue.forEach(function (handler) { |
|||
self.provider.onmessage = handler; |
|||
}); |
|||
}; |
|||
|
|||
var ws = new WebSocket(options.websockets); |
|||
|
|||
ws.onopen = function() { |
|||
closeWithSuccess(true); |
|||
}; |
|||
|
|||
ws.onerror = function() { |
|||
closeWithSuccess(false); |
|||
}; |
|||
}; |
|||
|
|||
/// Sends message forward to the provider, that is being used
|
|||
/// if provider is not yet set, enqueues the message
|
|||
AutoProvider.prototype.send = function (payload) { |
|||
if (this.provider) { |
|||
this.provider.send(payload); |
|||
return; |
|||
} |
|||
this.sendQueue.push(payload); |
|||
}; |
|||
|
|||
/// On incoming message sends the message to the provider that is currently being used
|
|||
Object.defineProperty(AutoProvider.prototype, 'onmessage', { |
|||
set: function (handler) { |
|||
if (this.provider) { |
|||
this.provider.onmessage = handler; |
|||
return; |
|||
} |
|||
this.onmessageQueue.push(handler); |
|||
} |
|||
}); |
|||
|
|||
module.exports = AutoProvider; |
@ -1,126 +0,0 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file httprpc.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Marian Oancea <marian@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
// TODO: is these line is supposed to be here?
|
|||
if (process.env.NODE_ENV !== 'build') { |
|||
var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // jshint ignore:line
|
|||
} |
|||
|
|||
/** |
|||
* HttpRpcProvider object prototype is implementing 'provider protocol' |
|||
* Should be used when we want to connect to ethereum backend over http && jsonrpc |
|||
* It's compatible with cpp client |
|||
* The contructor allows to specify host uri |
|||
* This provider is using in-browser polling mechanism |
|||
*/ |
|||
var HttpRpcProvider = function (host) { |
|||
this.handlers = []; |
|||
this.host = host; |
|||
}; |
|||
|
|||
/// Transforms inner message to proper jsonrpc object
|
|||
/// @param inner message object
|
|||
/// @returns jsonrpc object
|
|||
function formatJsonRpcObject(object) { |
|||
return { |
|||
jsonrpc: '2.0', |
|||
method: object.call, |
|||
params: object.args, |
|||
id: object._id |
|||
}; |
|||
} |
|||
|
|||
/// Transforms jsonrpc object to inner message
|
|||
/// @param incoming jsonrpc message
|
|||
/// @returns inner message object
|
|||
function formatJsonRpcMessage(message) { |
|||
var object = JSON.parse(message); |
|||
|
|||
return { |
|||
_id: object.id, |
|||
data: object.result, |
|||
error: object.error |
|||
}; |
|||
} |
|||
|
|||
/// Prototype object method
|
|||
/// Asynchronously sends request to server
|
|||
/// @param payload is inner message object
|
|||
/// @param cb is callback which is being called when response is comes back
|
|||
HttpRpcProvider.prototype.sendRequest = function (payload, cb) { |
|||
var data = formatJsonRpcObject(payload); |
|||
|
|||
var request = new XMLHttpRequest(); |
|||
request.open("POST", this.host, true); |
|||
request.send(JSON.stringify(data)); |
|||
request.onreadystatechange = function () { |
|||
if (request.readyState === 4 && cb) { |
|||
cb(request); |
|||
} |
|||
}; |
|||
}; |
|||
|
|||
/// Prototype object method
|
|||
/// Should be called when we want to send single api request to server
|
|||
/// Asynchronous
|
|||
/// On response it passes message to handlers
|
|||
/// @param payload is inner message object
|
|||
HttpRpcProvider.prototype.send = function (payload) { |
|||
var self = this; |
|||
this.sendRequest(payload, function (request) { |
|||
self.handlers.forEach(function (handler) { |
|||
handler.call(self, formatJsonRpcMessage(request.responseText)); |
|||
}); |
|||
}); |
|||
}; |
|||
|
|||
/// Prototype object method
|
|||
/// Should be called only for polling requests
|
|||
/// Asynchronous
|
|||
/// On response it passege message to handlers, but only if message's result is true or not empty array
|
|||
/// Otherwise response is being silently ignored
|
|||
/// @param payload is inner message object
|
|||
/// @id is id of poll that we are calling
|
|||
HttpRpcProvider.prototype.poll = function (payload, id) { |
|||
var self = this; |
|||
this.sendRequest(payload, function (request) { |
|||
var parsed = JSON.parse(request.responseText); |
|||
if (parsed.error || (parsed.result instanceof Array ? parsed.result.length === 0 : !parsed.result)) { |
|||
return; |
|||
} |
|||
self.handlers.forEach(function (handler) { |
|||
handler.call(self, {_event: payload.call, _id: id, data: parsed.result}); |
|||
}); |
|||
}); |
|||
}; |
|||
|
|||
/// Prototype object property
|
|||
/// Should be used to set message handlers for this provider
|
|||
Object.defineProperty(HttpRpcProvider.prototype, "onmessage", { |
|||
set: function (handler) { |
|||
this.handlers.push(handler); |
|||
} |
|||
}); |
|||
|
|||
module.exports = HttpRpcProvider; |
|||
|
@ -0,0 +1,66 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file httpsync.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Marian Oancea <marian@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
var HttpSyncProvider = function (host) { |
|||
this.handlers = []; |
|||
this.host = host || 'http://localhost:8080'; |
|||
}; |
|||
|
|||
/// Transforms inner message to proper jsonrpc object
|
|||
/// @param inner message object
|
|||
/// @returns jsonrpc object
|
|||
function formatJsonRpcObject(object) { |
|||
return { |
|||
jsonrpc: '2.0', |
|||
method: object.call, |
|||
params: object.args, |
|||
id: object._id |
|||
}; |
|||
} |
|||
|
|||
/// Transforms jsonrpc object to inner message
|
|||
/// @param incoming jsonrpc message
|
|||
/// @returns inner message object
|
|||
function formatJsonRpcMessage(message) { |
|||
var object = JSON.parse(message); |
|||
|
|||
return { |
|||
_id: object.id, |
|||
data: object.result, |
|||
error: object.error |
|||
}; |
|||
} |
|||
|
|||
HttpSyncProvider.prototype.send = function (payload) { |
|||
var data = formatJsonRpcObject(payload); |
|||
|
|||
var request = new XMLHttpRequest(); |
|||
request.open('POST', this.host, false); |
|||
request.send(JSON.stringify(data)); |
|||
|
|||
// check request.status
|
|||
return request.responseText; |
|||
}; |
|||
|
|||
module.exports = HttpSyncProvider; |
|||
|
@ -1,57 +0,0 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file qt.js |
|||
* @authors: |
|||
* Jeffrey Wilcke <jeff@ethdev.com> |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
/** |
|||
* QtProvider object prototype is implementing 'provider protocol' |
|||
* Should be used inside ethereum browser. It's compatible with cpp and go clients. |
|||
* It uses navigator.qt object to pass the messages to native bindings |
|||
*/ |
|||
var QtProvider = function() { |
|||
this.handlers = []; |
|||
|
|||
var self = this; |
|||
navigator.qt.onmessage = function (message) { |
|||
self.handlers.forEach(function (handler) { |
|||
handler.call(self, JSON.parse(message.data)); |
|||
}); |
|||
}; |
|||
}; |
|||
|
|||
/// Prototype object method
|
|||
/// Should be called when we want to send single api request to native bindings
|
|||
/// Asynchronous
|
|||
/// Response will be received by navigator.qt.onmessage method and passed to handlers
|
|||
/// @param payload is inner message object
|
|||
QtProvider.prototype.send = function(payload) { |
|||
navigator.qt.postMessage(JSON.stringify(payload)); |
|||
}; |
|||
|
|||
/// Prototype object property
|
|||
/// Should be used to set message handlers for this provider
|
|||
Object.defineProperty(QtProvider.prototype, "onmessage", { |
|||
set: function(handler) { |
|||
this.handlers.push(handler); |
|||
} |
|||
}); |
|||
|
|||
module.exports = QtProvider; |
@ -0,0 +1,32 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file qtsync.js |
|||
* @authors: |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Marian Oancea <marian@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
var QtSyncProvider = function () { |
|||
}; |
|||
|
|||
QtSyncProvider.prototype.send = function (payload) { |
|||
return navigator.qt.callMethod(JSON.stringify(payload)); |
|||
}; |
|||
|
|||
module.exports = QtSyncProvider; |
|||
|
@ -1,98 +0,0 @@ |
|||
/* |
|||
This file is part of ethereum.js. |
|||
|
|||
ethereum.js is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Lesser General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
ethereum.js is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public License |
|||
along with ethereum.js. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file websocket.js |
|||
* @authors: |
|||
* Jeffrey Wilcke <jeff@ethdev.com> |
|||
* Marek Kotewicz <marek@ethdev.com> |
|||
* Marian Oancea <marian@ethdev.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
// TODO: is these line is supposed to be here?
|
|||
if (process.env.NODE_ENV !== 'build') { |
|||
var WebSocket = require('ws'); // jshint ignore:line
|
|||
} |
|||
|
|||
/** |
|||
* WebSocketProvider object prototype is implementing 'provider protocol' |
|||
* Should be used when we want to connect to ethereum backend over websockets |
|||
* It's compatible with go client |
|||
* The constructor allows to specify host uri |
|||
*/ |
|||
var WebSocketProvider = function(host) { |
|||
|
|||
// onmessage handlers
|
|||
this.handlers = []; |
|||
|
|||
// queue will be filled with messages if send is invoked before the ws is ready
|
|||
this.queued = []; |
|||
this.ready = false; |
|||
|
|||
this.ws = new WebSocket(host); |
|||
|
|||
var self = this; |
|||
this.ws.onmessage = function(event) { |
|||
for(var i = 0; i < self.handlers.length; i++) { |
|||
self.handlers[i].call(self, JSON.parse(event.data), event); |
|||
} |
|||
}; |
|||
|
|||
this.ws.onopen = function() { |
|||
self.ready = true; |
|||
|
|||
for (var i = 0; i < self.queued.length; i++) { |
|||
// Resend
|
|||
self.send(self.queued[i]); |
|||
} |
|||
}; |
|||
}; |
|||
|
|||
/// Prototype object method
|
|||
/// Should be called when we want to send single api request to server
|
|||
/// Asynchronous, it's using websockets
|
|||
/// Response for the call will be received by ws.onmessage
|
|||
/// @param payload is inner message object
|
|||
WebSocketProvider.prototype.send = function(payload) { |
|||
if (this.ready) { |
|||
var data = JSON.stringify(payload); |
|||
|
|||
this.ws.send(data); |
|||
} else { |
|||
this.queued.push(payload); |
|||
} |
|||
}; |
|||
|
|||
/// Prototype object method
|
|||
/// Should be called to add handlers
|
|||
WebSocketProvider.prototype.onMessage = function(handler) { |
|||
this.handlers.push(handler); |
|||
}; |
|||
|
|||
/// Prototype object method
|
|||
/// Should be called to close websockets connection
|
|||
WebSocketProvider.prototype.unload = function() { |
|||
this.ws.close(); |
|||
}; |
|||
|
|||
/// Prototype object property
|
|||
/// Should be used to set message handlers for this provider
|
|||
Object.defineProperty(WebSocketProvider.prototype, "onmessage", { |
|||
set: function(provider) { this.onMessage(provider); } |
|||
}); |
|||
|
|||
if (typeof(module) !== "undefined") |
|||
module.exports = WebSocketProvider; |
@ -0,0 +1,69 @@ |
|||
|
|||
/** |
|||
* This plugin exposes 'evaluateExpression' method which should be used |
|||
* to evaluate natspec description |
|||
* It should be reloaded each time we want to evaluate set of expressions |
|||
* Just because of security reasons |
|||
* TODO: make use of sync api (once it's finished) and remove unnecessary |
|||
* code from 'getContractMethods' |
|||
* TODO: unify method signature creation with abi.js (and make a separate method from it) |
|||
*/ |
|||
|
|||
/// Should be called to copy values from object to global context
|
|||
var copyToContext = function (obj, context) { |
|||
var keys = Object.keys(obj); |
|||
keys.forEach(function (key) { |
|||
context[key] = obj[key]; |
|||
}); |
|||
} |
|||
|
|||
/// Function called to get all contract's storage values
|
|||
/// @returns hashmap with contract properties which are used
|
|||
var getContractProperties = function (address, abi) { |
|||
return {}; |
|||
}; |
|||
|
|||
/// Function called to get all contract's methods
|
|||
/// @returns hashmap with used contract's methods
|
|||
var getContractMethods = function (address, abi) { |
|||
return web3.eth.contract(address, abi); |
|||
}; |
|||
|
|||
/// Should be called to evaluate single expression
|
|||
/// Is internally using javascript's 'eval' method
|
|||
/// Should be checked if it is safe
|
|||
var evaluateExpression = function (expression) { |
|||
|
|||
var self = this; |
|||
var abi = web3._currentContractAbi; |
|||
var address = web3._currentContractAddress; |
|||
|
|||
var storage = getContractProperties(address, abi); |
|||
var methods = getContractMethods(address, abi); |
|||
|
|||
copyToContext(storage, self); |
|||
copyToContext(methods, self); |
|||
|
|||
// TODO: test if it is safe
|
|||
var evaluatedExpression = ""; |
|||
|
|||
// match everything in `` quotes
|
|||
var pattern = /\`(?:\\.|[^`\\])*\`/gim |
|||
var match; |
|||
var lastIndex = 0; |
|||
while ((match = pattern.exec(expression)) !== null) { |
|||
var startIndex = pattern.lastIndex - match[0].length; |
|||
|
|||
var toEval = match[0].slice(1, match[0].length - 1); |
|||
|
|||
evaluatedExpression += expression.slice(lastIndex, startIndex); |
|||
evaluatedExpression += eval(toEval).toString(); |
|||
|
|||
lastIndex = pattern.lastIndex; |
|||
} |
|||
|
|||
evaluatedExpression += expression.slice(lastIndex); |
|||
|
|||
return evaluatedExpression; |
|||
}; |
|||
|
@ -1,5 +1,6 @@ |
|||
<RCC> |
|||
<qresource prefix="/"> |
|||
<file alias="qml/WebPreview.qml">qml/WebPreviewStub.qml</file> |
|||
<file alias="qml/WebPreview.qml">qml/WebPreviewStub.qml</file> |
|||
<file alias="qml/CodeEditor.qml">qml/CodeEditor.qml</file> |
|||
</qresource> |
|||
</RCC> |
|||
|
@ -0,0 +1,69 @@ |
|||
import QtQuick 2.2 |
|||
import QtQuick.Controls 1.1 |
|||
import QtQuick.Layouts 1.0 |
|||
import QtQuick.Controls.Styles 1.1 |
|||
import CodeEditorExtensionManager 1.0 |
|||
import QtWebEngine 1.0 |
|||
|
|||
Component { |
|||
Item { |
|||
signal editorTextChanged |
|||
property string currentText: "" |
|||
property string currentMode: "" |
|||
property bool initialized: false |
|||
|
|||
function setText(text, mode) { |
|||
currentText = text; |
|||
currentMode = mode; |
|||
if (initialized) { |
|||
editorBrowser.runJavaScript("setTextBase64(\"" + Qt.btoa(text) + "\")"); |
|||
editorBrowser.runJavaScript("setMode(\"" + mode + "\")"); |
|||
} |
|||
editorBrowser.forceActiveFocus(); |
|||
} |
|||
|
|||
function getText() { |
|||
return currentText; |
|||
} |
|||
|
|||
anchors.top: parent.top |
|||
id: codeEditorView |
|||
anchors.fill: parent |
|||
WebEngineView { |
|||
id: editorBrowser |
|||
url: "qrc:///qml/html/codeeditor.html" |
|||
anchors.fill: parent |
|||
onJavaScriptConsoleMessage: { |
|||
console.log("editor: " + sourceID + ":" + lineNumber + ":" + message); |
|||
} |
|||
|
|||
onLoadingChanged: |
|||
{ |
|||
if (!loading) { |
|||
initialized = true; |
|||
setText(currentText, currentMode); |
|||
runJavaScript("getTextChanged()", function(result) { }); |
|||
pollTimer.running = true; |
|||
} |
|||
} |
|||
|
|||
Timer |
|||
{ |
|||
id: pollTimer |
|||
interval: 30 |
|||
running: false |
|||
repeat: true |
|||
onTriggered: { |
|||
editorBrowser.runJavaScript("getTextChanged()", function(result) { |
|||
if (result === true) { |
|||
editorBrowser.runJavaScript("getText()" , function(textValue) { |
|||
currentText = textValue; |
|||
editorTextChanged(); |
|||
}); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,71 @@ |
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|||
|
|||
// Because sometimes you need to style the cursor's line.
|
|||
//
|
|||
// Adds an option 'styleActiveLine' which, when enabled, gives the
|
|||
// active line's wrapping <div> the CSS class "CodeMirror-activeline",
|
|||
// and gives its background <div> the class "CodeMirror-activeline-background".
|
|||
|
|||
(function(mod) { |
|||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|||
mod(require("../../lib/codemirror")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
"use strict"; |
|||
var WRAP_CLASS = "CodeMirror-activeline"; |
|||
var BACK_CLASS = "CodeMirror-activeline-background"; |
|||
|
|||
CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) { |
|||
var prev = old && old != CodeMirror.Init; |
|||
if (val && !prev) { |
|||
cm.state.activeLines = []; |
|||
updateActiveLines(cm, cm.listSelections()); |
|||
cm.on("beforeSelectionChange", selectionChange); |
|||
} else if (!val && prev) { |
|||
cm.off("beforeSelectionChange", selectionChange); |
|||
clearActiveLines(cm); |
|||
delete cm.state.activeLines; |
|||
} |
|||
}); |
|||
|
|||
function clearActiveLines(cm) { |
|||
for (var i = 0; i < cm.state.activeLines.length; i++) { |
|||
cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS); |
|||
cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS); |
|||
} |
|||
} |
|||
|
|||
function sameArray(a, b) { |
|||
if (a.length != b.length) return false; |
|||
for (var i = 0; i < a.length; i++) |
|||
if (a[i] != b[i]) return false; |
|||
return true; |
|||
} |
|||
|
|||
function updateActiveLines(cm, ranges) { |
|||
var active = []; |
|||
for (var i = 0; i < ranges.length; i++) { |
|||
var range = ranges[i]; |
|||
if (!range.empty()) continue; |
|||
var line = cm.getLineHandleVisualStart(range.head.line); |
|||
if (active[active.length - 1] != line) active.push(line); |
|||
} |
|||
if (sameArray(cm.state.activeLines, active)) return; |
|||
cm.operation(function() { |
|||
clearActiveLines(cm); |
|||
for (var i = 0; i < active.length; i++) { |
|||
cm.addLineClass(active[i], "wrap", WRAP_CLASS); |
|||
cm.addLineClass(active[i], "background", BACK_CLASS); |
|||
} |
|||
cm.state.activeLines = active; |
|||
}); |
|||
} |
|||
|
|||
function selectionChange(cm, sel) { |
|||
updateActiveLines(cm, sel.ranges); |
|||
} |
|||
}); |
@ -0,0 +1,311 @@ |
|||
/* BASICS */ |
|||
|
|||
.CodeMirror { |
|||
/* Set height, width, borders, and global font properties here */ |
|||
font-family: monospace; |
|||
border: 1px solid black; |
|||
height: 100%; |
|||
font-size:16px |
|||
} |
|||
|
|||
/* PADDING */ |
|||
|
|||
.CodeMirror-lines { |
|||
padding: 4px 0; /* Vertical padding around content */ |
|||
} |
|||
.CodeMirror pre { |
|||
padding: 0 4px; /* Horizontal padding of content */ |
|||
} |
|||
|
|||
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { |
|||
background-color: white; /* The little square between H and V scrollbars */ |
|||
} |
|||
|
|||
/* GUTTER */ |
|||
|
|||
.CodeMirror-gutters { |
|||
border-right: 1px solid #ddd; |
|||
background-color: #f7f7f7; |
|||
white-space: nowrap; |
|||
} |
|||
.CodeMirror-linenumbers {} |
|||
.CodeMirror-linenumber { |
|||
padding: 0 3px 0 5px; |
|||
min-width: 20px; |
|||
text-align: right; |
|||
color: #999; |
|||
-moz-box-sizing: content-box; |
|||
box-sizing: content-box; |
|||
} |
|||
|
|||
.CodeMirror-guttermarker { color: black; } |
|||
.CodeMirror-guttermarker-subtle { color: #999; } |
|||
|
|||
/* CURSOR */ |
|||
|
|||
.CodeMirror div.CodeMirror-cursor { |
|||
border-left: 1px solid black; |
|||
} |
|||
/* Shown when moving in bi-directional text */ |
|||
.CodeMirror div.CodeMirror-secondarycursor { |
|||
border-left: 1px solid silver; |
|||
} |
|||
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor { |
|||
width: auto; |
|||
border: 0; |
|||
background: #7e7; |
|||
} |
|||
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors { |
|||
z-index: 1; |
|||
} |
|||
|
|||
.cm-animate-fat-cursor { |
|||
width: auto; |
|||
border: 0; |
|||
-webkit-animation: blink 1.06s steps(1) infinite; |
|||
-moz-animation: blink 1.06s steps(1) infinite; |
|||
animation: blink 1.06s steps(1) infinite; |
|||
} |
|||
@-moz-keyframes blink { |
|||
0% { background: #7e7; } |
|||
50% { background: none; } |
|||
100% { background: #7e7; } |
|||
} |
|||
@-webkit-keyframes blink { |
|||
0% { background: #7e7; } |
|||
50% { background: none; } |
|||
100% { background: #7e7; } |
|||
} |
|||
@keyframes blink { |
|||
0% { background: #7e7; } |
|||
50% { background: none; } |
|||
100% { background: #7e7; } |
|||
} |
|||
|
|||
/* Can style cursor different in overwrite (non-insert) mode */ |
|||
div.CodeMirror-overwrite div.CodeMirror-cursor {} |
|||
|
|||
.cm-tab { display: inline-block; text-decoration: inherit; } |
|||
|
|||
.CodeMirror-ruler { |
|||
border-left: 1px solid #ccc; |
|||
position: absolute; |
|||
} |
|||
|
|||
/* DEFAULT THEME */ |
|||
|
|||
.cm-s-default .cm-keyword {color: #708;} |
|||
.cm-s-default .cm-atom {color: #219;} |
|||
.cm-s-default .cm-number {color: #164;} |
|||
.cm-s-default .cm-def {color: #00f;} |
|||
.cm-s-default .cm-variable, |
|||
.cm-s-default .cm-punctuation, |
|||
.cm-s-default .cm-property, |
|||
.cm-s-default .cm-operator {} |
|||
.cm-s-default .cm-variable-2 {color: #05a;} |
|||
.cm-s-default .cm-variable-3 {color: #085;} |
|||
.cm-s-default .cm-comment {color: #a50;} |
|||
.cm-s-default .cm-string {color: #a11;} |
|||
.cm-s-default .cm-string-2 {color: #f50;} |
|||
.cm-s-default .cm-meta {color: #555;} |
|||
.cm-s-default .cm-qualifier {color: #555;} |
|||
.cm-s-default .cm-builtin {color: #30a;} |
|||
.cm-s-default .cm-bracket {color: #997;} |
|||
.cm-s-default .cm-tag {color: #170;} |
|||
.cm-s-default .cm-attribute {color: #00c;} |
|||
.cm-s-default .cm-header {color: blue;} |
|||
.cm-s-default .cm-quote {color: #090;} |
|||
.cm-s-default .cm-hr {color: #999;} |
|||
.cm-s-default .cm-link {color: #00c;} |
|||
|
|||
.cm-negative {color: #d44;} |
|||
.cm-positive {color: #292;} |
|||
.cm-header, .cm-strong {font-weight: bold;} |
|||
.cm-em {font-style: italic;} |
|||
.cm-link {text-decoration: underline;} |
|||
.cm-strikethrough {text-decoration: line-through;} |
|||
|
|||
.cm-s-default .cm-error {color: #f00;} |
|||
.cm-invalidchar {color: #f00;} |
|||
|
|||
/* Default styles for common addons */ |
|||
|
|||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} |
|||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} |
|||
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } |
|||
.CodeMirror-activeline-background {background: #e8f2ff;} |
|||
|
|||
/* STOP */ |
|||
|
|||
/* The rest of this file contains styles related to the mechanics of |
|||
the editor. You probably shouldn't touch them. */ |
|||
|
|||
.CodeMirror { |
|||
line-height: 1; |
|||
position: relative; |
|||
overflow: hidden; |
|||
background: white; |
|||
color: black; |
|||
} |
|||
|
|||
.CodeMirror-scroll { |
|||
overflow: scroll !important; /* Things will break if this is overridden */ |
|||
/* 30px is the magic margin used to hide the element's real scrollbars */ |
|||
/* See overflow: hidden in .CodeMirror */ |
|||
margin-bottom: -30px; margin-right: -30px; |
|||
padding-bottom: 30px; |
|||
height: 100%; |
|||
outline: none; /* Prevent dragging from highlighting the element */ |
|||
position: relative; |
|||
-moz-box-sizing: content-box; |
|||
box-sizing: content-box; |
|||
} |
|||
.CodeMirror-sizer { |
|||
position: relative; |
|||
border-right: 30px solid transparent; |
|||
-moz-box-sizing: content-box; |
|||
box-sizing: content-box; |
|||
} |
|||
|
|||
/* The fake, visible scrollbars. Used to force redraw during scrolling |
|||
before actuall scrolling happens, thus preventing shaking and |
|||
flickering artifacts. */ |
|||
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { |
|||
position: absolute; |
|||
z-index: 6; |
|||
display: none; |
|||
} |
|||
.CodeMirror-vscrollbar { |
|||
right: 0; top: 0; |
|||
overflow-x: hidden; |
|||
overflow-y: scroll; |
|||
} |
|||
.CodeMirror-hscrollbar { |
|||
bottom: 0; left: 0; |
|||
overflow-y: hidden; |
|||
overflow-x: scroll; |
|||
} |
|||
.CodeMirror-scrollbar-filler { |
|||
right: 0; bottom: 0; |
|||
} |
|||
.CodeMirror-gutter-filler { |
|||
left: 0; bottom: 0; |
|||
} |
|||
|
|||
.CodeMirror-gutters { |
|||
position: absolute; left: 0; top: 0; |
|||
z-index: 3; |
|||
} |
|||
.CodeMirror-gutter { |
|||
white-space: normal; |
|||
height: 100%; |
|||
-moz-box-sizing: content-box; |
|||
box-sizing: content-box; |
|||
display: inline-block; |
|||
margin-bottom: -30px; |
|||
/* Hack to make IE7 behave */ |
|||
*zoom:1; |
|||
*display:inline; |
|||
} |
|||
.CodeMirror-gutter-wrapper { |
|||
position: absolute; |
|||
z-index: 4; |
|||
height: 100%; |
|||
} |
|||
.CodeMirror-gutter-elt { |
|||
position: absolute; |
|||
cursor: default; |
|||
z-index: 4; |
|||
} |
|||
|
|||
.CodeMirror-lines { |
|||
cursor: text; |
|||
min-height: 1px; /* prevents collapsing before first draw */ |
|||
} |
|||
.CodeMirror pre { |
|||
/* Reset some styles that the rest of the page might have set */ |
|||
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; |
|||
border-width: 0; |
|||
background: transparent; |
|||
font-family: inherit; |
|||
font-size: inherit; |
|||
margin: 0; |
|||
white-space: pre; |
|||
word-wrap: normal; |
|||
line-height: inherit; |
|||
color: inherit; |
|||
z-index: 2; |
|||
position: relative; |
|||
overflow: visible; |
|||
} |
|||
.CodeMirror-wrap pre { |
|||
word-wrap: break-word; |
|||
white-space: pre-wrap; |
|||
word-break: normal; |
|||
} |
|||
|
|||
.CodeMirror-linebackground { |
|||
position: absolute; |
|||
left: 0; right: 0; top: 0; bottom: 0; |
|||
z-index: 0; |
|||
} |
|||
|
|||
.CodeMirror-linewidget { |
|||
position: relative; |
|||
z-index: 2; |
|||
overflow: auto; |
|||
} |
|||
|
|||
.CodeMirror-widget {} |
|||
|
|||
.CodeMirror-measure { |
|||
position: absolute; |
|||
width: 100%; |
|||
height: 0; |
|||
overflow: hidden; |
|||
visibility: hidden; |
|||
} |
|||
.CodeMirror-measure pre { position: static; } |
|||
|
|||
.CodeMirror div.CodeMirror-cursor { |
|||
position: absolute; |
|||
border-right: none; |
|||
width: 0; |
|||
} |
|||
|
|||
div.CodeMirror-cursors { |
|||
visibility: hidden; |
|||
position: relative; |
|||
z-index: 3; |
|||
} |
|||
.CodeMirror-focused div.CodeMirror-cursors { |
|||
visibility: visible; |
|||
} |
|||
|
|||
.CodeMirror-selected { background: #d9d9d9; } |
|||
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } |
|||
.CodeMirror-crosshair { cursor: crosshair; } |
|||
|
|||
.cm-searching { |
|||
background: #ffa; |
|||
background: rgba(255, 255, 0, .4); |
|||
} |
|||
|
|||
/* IE7 hack to prevent it from returning funny offsetTops on the spans */ |
|||
.CodeMirror span { *vertical-align: text-bottom; } |
|||
|
|||
/* Used to force a border model for a node */ |
|||
.cm-force-border { padding-right: .1px; } |
|||
|
|||
@media print { |
|||
/* Hide the cursor when printing */ |
|||
.CodeMirror div.CodeMirror-cursors { |
|||
visibility: hidden; |
|||
} |
|||
} |
|||
|
|||
/* See issue #2901 */ |
|||
.cm-tab-wrap-hack:after { content: ''; } |
|||
|
|||
/* Help users use markselection to safely style text background */ |
|||
span.CodeMirror-selectedtext { background: none; } |
File diff suppressed because it is too large
@ -0,0 +1,717 @@ |
|||
// 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")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
"use strict"; |
|||
|
|||
CodeMirror.defineMode("css", function(config, parserConfig) { |
|||
if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css"); |
|||
|
|||
var indentUnit = config.indentUnit, |
|||
tokenHooks = parserConfig.tokenHooks, |
|||
mediaTypes = parserConfig.mediaTypes || {}, |
|||
mediaFeatures = parserConfig.mediaFeatures || {}, |
|||
propertyKeywords = parserConfig.propertyKeywords || {}, |
|||
nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {}, |
|||
colorKeywords = parserConfig.colorKeywords || {}, |
|||
valueKeywords = parserConfig.valueKeywords || {}, |
|||
fontProperties = parserConfig.fontProperties || {}, |
|||
allowNested = parserConfig.allowNested; |
|||
|
|||
var type, override; |
|||
function ret(style, tp) { type = tp; return style; } |
|||
|
|||
// Tokenizers
|
|||
|
|||
function tokenBase(stream, state) { |
|||
var ch = stream.next(); |
|||
if (tokenHooks[ch]) { |
|||
var result = tokenHooks[ch](stream, state); |
|||
if (result !== false) return result; |
|||
} |
|||
if (ch == "@") { |
|||
stream.eatWhile(/[\w\\\-]/); |
|||
return ret("def", stream.current()); |
|||
} else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) { |
|||
return ret(null, "compare"); |
|||
} else if (ch == "\"" || ch == "'") { |
|||
state.tokenize = tokenString(ch); |
|||
return state.tokenize(stream, state); |
|||
} else if (ch == "#") { |
|||
stream.eatWhile(/[\w\\\-]/); |
|||
return ret("atom", "hash"); |
|||
} else if (ch == "!") { |
|||
stream.match(/^\s*\w*/); |
|||
return ret("keyword", "important"); |
|||
} else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) { |
|||
stream.eatWhile(/[\w.%]/); |
|||
return ret("number", "unit"); |
|||
} else if (ch === "-") { |
|||
if (/[\d.]/.test(stream.peek())) { |
|||
stream.eatWhile(/[\w.%]/); |
|||
return ret("number", "unit"); |
|||
} else if (stream.match(/^\w+-/)) { |
|||
return ret("meta", "meta"); |
|||
} |
|||
} else if (/[,+>*\/]/.test(ch)) { |
|||
return ret(null, "select-op"); |
|||
} else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) { |
|||
return ret("qualifier", "qualifier"); |
|||
} else if (/[:;{}\[\]\(\)]/.test(ch)) { |
|||
return ret(null, ch); |
|||
} else if (ch == "u" && stream.match("rl(")) { |
|||
stream.backUp(1); |
|||
state.tokenize = tokenParenthesized; |
|||
return ret("property", "word"); |
|||
} else if (/[\w\\\-]/.test(ch)) { |
|||
stream.eatWhile(/[\w\\\-]/); |
|||
return ret("property", "word"); |
|||
} else { |
|||
return ret(null, null); |
|||
} |
|||
} |
|||
|
|||
function tokenString(quote) { |
|||
return function(stream, state) { |
|||
var escaped = false, ch; |
|||
while ((ch = stream.next()) != null) { |
|||
if (ch == quote && !escaped) { |
|||
if (quote == ")") stream.backUp(1); |
|||
break; |
|||
} |
|||
escaped = !escaped && ch == "\\"; |
|||
} |
|||
if (ch == quote || !escaped && quote != ")") state.tokenize = null; |
|||
return ret("string", "string"); |
|||
}; |
|||
} |
|||
|
|||
function tokenParenthesized(stream, state) { |
|||
stream.next(); // Must be '('
|
|||
if (!stream.match(/\s*[\"\')]/, false)) |
|||
state.tokenize = tokenString(")"); |
|||
else |
|||
state.tokenize = null; |
|||
return ret(null, "("); |
|||
} |
|||
|
|||
// Context management
|
|||
|
|||
function Context(type, indent, prev) { |
|||
this.type = type; |
|||
this.indent = indent; |
|||
this.prev = prev; |
|||
} |
|||
|
|||
function pushContext(state, stream, type) { |
|||
state.context = new Context(type, stream.indentation() + indentUnit, state.context); |
|||
return type; |
|||
} |
|||
|
|||
function popContext(state) { |
|||
state.context = state.context.prev; |
|||
return state.context.type; |
|||
} |
|||
|
|||
function pass(type, stream, state) { |
|||
return states[state.context.type](type, stream, state); |
|||
} |
|||
function popAndPass(type, stream, state, n) { |
|||
for (var i = n || 1; i > 0; i--) |
|||
state.context = state.context.prev; |
|||
return pass(type, stream, state); |
|||
} |
|||
|
|||
// Parser
|
|||
|
|||
function wordAsValue(stream) { |
|||
var word = stream.current().toLowerCase(); |
|||
if (valueKeywords.hasOwnProperty(word)) |
|||
override = "atom"; |
|||
else if (colorKeywords.hasOwnProperty(word)) |
|||
override = "keyword"; |
|||
else |
|||
override = "variable"; |
|||
} |
|||
|
|||
var states = {}; |
|||
|
|||
states.top = function(type, stream, state) { |
|||
if (type == "{") { |
|||
return pushContext(state, stream, "block"); |
|||
} else if (type == "}" && state.context.prev) { |
|||
return popContext(state); |
|||
} else if (type == "@media") { |
|||
return pushContext(state, stream, "media"); |
|||
} else if (type == "@font-face") { |
|||
return "font_face_before"; |
|||
} else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) { |
|||
return "keyframes"; |
|||
} else if (type && type.charAt(0) == "@") { |
|||
return pushContext(state, stream, "at"); |
|||
} else if (type == "hash") { |
|||
override = "builtin"; |
|||
} else if (type == "word") { |
|||
override = "tag"; |
|||
} else if (type == "variable-definition") { |
|||
return "maybeprop"; |
|||
} else if (type == "interpolation") { |
|||
return pushContext(state, stream, "interpolation"); |
|||
} else if (type == ":") { |
|||
return "pseudo"; |
|||
} else if (allowNested && type == "(") { |
|||
return pushContext(state, stream, "parens"); |
|||
} |
|||
return state.context.type; |
|||
}; |
|||
|
|||
states.block = function(type, stream, state) { |
|||
if (type == "word") { |
|||
var word = stream.current().toLowerCase(); |
|||
if (propertyKeywords.hasOwnProperty(word)) { |
|||
override = "property"; |
|||
return "maybeprop"; |
|||
} else if (nonStandardPropertyKeywords.hasOwnProperty(word)) { |
|||
override = "string-2"; |
|||
return "maybeprop"; |
|||
} else if (allowNested) { |
|||
override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag"; |
|||
return "block"; |
|||
} else { |
|||
override += " error"; |
|||
return "maybeprop"; |
|||
} |
|||
} else if (type == "meta") { |
|||
return "block"; |
|||
} else if (!allowNested && (type == "hash" || type == "qualifier")) { |
|||
override = "error"; |
|||
return "block"; |
|||
} else { |
|||
return states.top(type, stream, state); |
|||
} |
|||
}; |
|||
|
|||
states.maybeprop = function(type, stream, state) { |
|||
if (type == ":") return pushContext(state, stream, "prop"); |
|||
return pass(type, stream, state); |
|||
}; |
|||
|
|||
states.prop = function(type, stream, state) { |
|||
if (type == ";") return popContext(state); |
|||
if (type == "{" && allowNested) return pushContext(state, stream, "propBlock"); |
|||
if (type == "}" || type == "{") return popAndPass(type, stream, state); |
|||
if (type == "(") return pushContext(state, stream, "parens"); |
|||
|
|||
if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) { |
|||
override += " error"; |
|||
} else if (type == "word") { |
|||
wordAsValue(stream); |
|||
} else if (type == "interpolation") { |
|||
return pushContext(state, stream, "interpolation"); |
|||
} |
|||
return "prop"; |
|||
}; |
|||
|
|||
states.propBlock = function(type, _stream, state) { |
|||
if (type == "}") return popContext(state); |
|||
if (type == "word") { override = "property"; return "maybeprop"; } |
|||
return state.context.type; |
|||
}; |
|||
|
|||
states.parens = function(type, stream, state) { |
|||
if (type == "{" || type == "}") return popAndPass(type, stream, state); |
|||
if (type == ")") return popContext(state); |
|||
if (type == "(") return pushContext(state, stream, "parens"); |
|||
if (type == "word") wordAsValue(stream); |
|||
return "parens"; |
|||
}; |
|||
|
|||
states.pseudo = function(type, stream, state) { |
|||
if (type == "word") { |
|||
override = "variable-3"; |
|||
return state.context.type; |
|||
} |
|||
return pass(type, stream, state); |
|||
}; |
|||
|
|||
states.media = function(type, stream, state) { |
|||
if (type == "(") return pushContext(state, stream, "media_parens"); |
|||
if (type == "}") return popAndPass(type, stream, state); |
|||
if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top"); |
|||
|
|||
if (type == "word") { |
|||
var word = stream.current().toLowerCase(); |
|||
if (word == "only" || word == "not" || word == "and") |
|||
override = "keyword"; |
|||
else if (mediaTypes.hasOwnProperty(word)) |
|||
override = "attribute"; |
|||
else if (mediaFeatures.hasOwnProperty(word)) |
|||
override = "property"; |
|||
else |
|||
override = "error"; |
|||
} |
|||
return state.context.type; |
|||
}; |
|||
|
|||
states.media_parens = function(type, stream, state) { |
|||
if (type == ")") return popContext(state); |
|||
if (type == "{" || type == "}") return popAndPass(type, stream, state, 2); |
|||
return states.media(type, stream, state); |
|||
}; |
|||
|
|||
states.font_face_before = function(type, stream, state) { |
|||
if (type == "{") |
|||
return pushContext(state, stream, "font_face"); |
|||
return pass(type, stream, state); |
|||
}; |
|||
|
|||
states.font_face = function(type, stream, state) { |
|||
if (type == "}") return popContext(state); |
|||
if (type == "word") { |
|||
if (!fontProperties.hasOwnProperty(stream.current().toLowerCase())) |
|||
override = "error"; |
|||
else |
|||
override = "property"; |
|||
return "maybeprop"; |
|||
} |
|||
return "font_face"; |
|||
}; |
|||
|
|||
states.keyframes = function(type, stream, state) { |
|||
if (type == "word") { override = "variable"; return "keyframes"; } |
|||
if (type == "{") return pushContext(state, stream, "top"); |
|||
return pass(type, stream, state); |
|||
}; |
|||
|
|||
states.at = function(type, stream, state) { |
|||
if (type == ";") return popContext(state); |
|||
if (type == "{" || type == "}") return popAndPass(type, stream, state); |
|||
if (type == "word") override = "tag"; |
|||
else if (type == "hash") override = "builtin"; |
|||
return "at"; |
|||
}; |
|||
|
|||
states.interpolation = function(type, stream, state) { |
|||
if (type == "}") return popContext(state); |
|||
if (type == "{" || type == ";") return popAndPass(type, stream, state); |
|||
if (type != "variable") override = "error"; |
|||
return "interpolation"; |
|||
}; |
|||
|
|||
return { |
|||
startState: function(base) { |
|||
return {tokenize: null, |
|||
state: "top", |
|||
context: new Context("top", base || 0, null)}; |
|||
}, |
|||
|
|||
token: function(stream, state) { |
|||
if (!state.tokenize && stream.eatSpace()) return null; |
|||
var style = (state.tokenize || tokenBase)(stream, state); |
|||
if (style && typeof style == "object") { |
|||
type = style[1]; |
|||
style = style[0]; |
|||
} |
|||
override = style; |
|||
state.state = states[state.state](type, stream, state); |
|||
return override; |
|||
}, |
|||
|
|||
indent: function(state, textAfter) { |
|||
var cx = state.context, ch = textAfter && textAfter.charAt(0); |
|||
var indent = cx.indent; |
|||
if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev; |
|||
if (cx.prev && |
|||
(ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") || |
|||
ch == ")" && (cx.type == "parens" || cx.type == "media_parens") || |
|||
ch == "{" && (cx.type == "at" || cx.type == "media"))) { |
|||
indent = cx.indent - indentUnit; |
|||
cx = cx.prev; |
|||
} |
|||
return indent; |
|||
}, |
|||
|
|||
electricChars: "}", |
|||
blockCommentStart: "/*", |
|||
blockCommentEnd: "*/", |
|||
fold: "brace" |
|||
}; |
|||
}); |
|||
|
|||
function keySet(array) { |
|||
var keys = {}; |
|||
for (var i = 0; i < array.length; ++i) { |
|||
keys[array[i]] = true; |
|||
} |
|||
return keys; |
|||
} |
|||
|
|||
var mediaTypes_ = [ |
|||
"all", "aural", "braille", "handheld", "print", "projection", "screen", |
|||
"tty", "tv", "embossed" |
|||
], mediaTypes = keySet(mediaTypes_); |
|||
|
|||
var mediaFeatures_ = [ |
|||
"width", "min-width", "max-width", "height", "min-height", "max-height", |
|||
"device-width", "min-device-width", "max-device-width", "device-height", |
|||
"min-device-height", "max-device-height", "aspect-ratio", |
|||
"min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio", |
|||
"min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color", |
|||
"max-color", "color-index", "min-color-index", "max-color-index", |
|||
"monochrome", "min-monochrome", "max-monochrome", "resolution", |
|||
"min-resolution", "max-resolution", "scan", "grid" |
|||
], mediaFeatures = keySet(mediaFeatures_); |
|||
|
|||
var propertyKeywords_ = [ |
|||
"align-content", "align-items", "align-self", "alignment-adjust", |
|||
"alignment-baseline", "anchor-point", "animation", "animation-delay", |
|||
"animation-direction", "animation-duration", "animation-fill-mode", |
|||
"animation-iteration-count", "animation-name", "animation-play-state", |
|||
"animation-timing-function", "appearance", "azimuth", "backface-visibility", |
|||
"background", "background-attachment", "background-clip", "background-color", |
|||
"background-image", "background-origin", "background-position", |
|||
"background-repeat", "background-size", "baseline-shift", "binding", |
|||
"bleed", "bookmark-label", "bookmark-level", "bookmark-state", |
|||
"bookmark-target", "border", "border-bottom", "border-bottom-color", |
|||
"border-bottom-left-radius", "border-bottom-right-radius", |
|||
"border-bottom-style", "border-bottom-width", "border-collapse", |
|||
"border-color", "border-image", "border-image-outset", |
|||
"border-image-repeat", "border-image-slice", "border-image-source", |
|||
"border-image-width", "border-left", "border-left-color", |
|||
"border-left-style", "border-left-width", "border-radius", "border-right", |
|||
"border-right-color", "border-right-style", "border-right-width", |
|||
"border-spacing", "border-style", "border-top", "border-top-color", |
|||
"border-top-left-radius", "border-top-right-radius", "border-top-style", |
|||
"border-top-width", "border-width", "bottom", "box-decoration-break", |
|||
"box-shadow", "box-sizing", "break-after", "break-before", "break-inside", |
|||
"caption-side", "clear", "clip", "color", "color-profile", "column-count", |
|||
"column-fill", "column-gap", "column-rule", "column-rule-color", |
|||
"column-rule-style", "column-rule-width", "column-span", "column-width", |
|||
"columns", "content", "counter-increment", "counter-reset", "crop", "cue", |
|||
"cue-after", "cue-before", "cursor", "direction", "display", |
|||
"dominant-baseline", "drop-initial-after-adjust", |
|||
"drop-initial-after-align", "drop-initial-before-adjust", |
|||
"drop-initial-before-align", "drop-initial-size", "drop-initial-value", |
|||
"elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis", |
|||
"flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap", |
|||
"float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings", |
|||
"font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust", |
|||
"font-stretch", "font-style", "font-synthesis", "font-variant", |
|||
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian", |
|||
"font-variant-ligatures", "font-variant-numeric", "font-variant-position", |
|||
"font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", |
|||
"grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end", |
|||
"grid-column-start", "grid-row", "grid-row-end", "grid-row-start", |
|||
"grid-template", "grid-template-areas", "grid-template-columns", |
|||
"grid-template-rows", "hanging-punctuation", "height", "hyphens", |
|||
"icon", "image-orientation", "image-rendering", "image-resolution", |
|||
"inline-box-align", "justify-content", "left", "letter-spacing", |
|||
"line-break", "line-height", "line-stacking", "line-stacking-ruby", |
|||
"line-stacking-shift", "line-stacking-strategy", "list-style", |
|||
"list-style-image", "list-style-position", "list-style-type", "margin", |
|||
"margin-bottom", "margin-left", "margin-right", "margin-top", |
|||
"marker-offset", "marks", "marquee-direction", "marquee-loop", |
|||
"marquee-play-count", "marquee-speed", "marquee-style", "max-height", |
|||
"max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index", |
|||
"nav-left", "nav-right", "nav-up", "object-fit", "object-position", |
|||
"opacity", "order", "orphans", "outline", |
|||
"outline-color", "outline-offset", "outline-style", "outline-width", |
|||
"overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y", |
|||
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top", |
|||
"page", "page-break-after", "page-break-before", "page-break-inside", |
|||
"page-policy", "pause", "pause-after", "pause-before", "perspective", |
|||
"perspective-origin", "pitch", "pitch-range", "play-during", "position", |
|||
"presentation-level", "punctuation-trim", "quotes", "region-break-after", |
|||
"region-break-before", "region-break-inside", "region-fragment", |
|||
"rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness", |
|||
"right", "rotation", "rotation-point", "ruby-align", "ruby-overhang", |
|||
"ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin", |
|||
"shape-outside", "size", "speak", "speak-as", "speak-header", |
|||
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set", |
|||
"tab-size", "table-layout", "target", "target-name", "target-new", |
|||
"target-position", "text-align", "text-align-last", "text-decoration", |
|||
"text-decoration-color", "text-decoration-line", "text-decoration-skip", |
|||
"text-decoration-style", "text-emphasis", "text-emphasis-color", |
|||
"text-emphasis-position", "text-emphasis-style", "text-height", |
|||
"text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow", |
|||
"text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position", |
|||
"text-wrap", "top", "transform", "transform-origin", "transform-style", |
|||
"transition", "transition-delay", "transition-duration", |
|||
"transition-property", "transition-timing-function", "unicode-bidi", |
|||
"vertical-align", "visibility", "voice-balance", "voice-duration", |
|||
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress", |
|||
"voice-volume", "volume", "white-space", "widows", "width", "word-break", |
|||
"word-spacing", "word-wrap", "z-index", |
|||
// SVG-specific
|
|||
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color", |
|||
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events", |
|||
"color-interpolation", "color-interpolation-filters", |
|||
"color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering", |
|||
"marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke", |
|||
"stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", |
|||
"stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering", |
|||
"baseline-shift", "dominant-baseline", "glyph-orientation-horizontal", |
|||
"glyph-orientation-vertical", "text-anchor", "writing-mode" |
|||
], propertyKeywords = keySet(propertyKeywords_); |
|||
|
|||
var nonStandardPropertyKeywords_ = [ |
|||
"scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color", |
|||
"scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color", |
|||
"scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside", |
|||
"searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button", |
|||
"searchfield-results-decoration", "zoom" |
|||
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_); |
|||
|
|||
var colorKeywords_ = [ |
|||
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", |
|||
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", |
|||
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", |
|||
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", |
|||
"darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", |
|||
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", |
|||
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet", |
|||
"deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", |
|||
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", |
|||
"gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew", |
|||
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender", |
|||
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", |
|||
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink", |
|||
"lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", |
|||
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", |
|||
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", |
|||
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", |
|||
"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", |
|||
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered", |
|||
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred", |
|||
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", |
|||
"purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown", |
|||
"salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", |
|||
"slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", |
|||
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", |
|||
"whitesmoke", "yellow", "yellowgreen" |
|||
], colorKeywords = keySet(colorKeywords_); |
|||
|
|||
var valueKeywords_ = [ |
|||
"above", "absolute", "activeborder", "activecaption", "afar", |
|||
"after-white-space", "ahead", "alias", "all", "all-scroll", "alternate", |
|||
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace", |
|||
"arabic-indic", "armenian", "asterisks", "auto", "avoid", "avoid-column", "avoid-page", |
|||
"avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary", |
|||
"bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box", |
|||
"both", "bottom", "break", "break-all", "break-word", "button", "button-bevel", |
|||
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian", |
|||
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret", |
|||
"cell", "center", "checkbox", "circle", "cjk-earthly-branch", |
|||
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote", |
|||
"col-resize", "collapse", "column", "compact", "condensed", "contain", "content", |
|||
"content-box", "context-menu", "continuous", "copy", "cover", "crop", |
|||
"cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal", |
|||
"decimal-leading-zero", "default", "default-button", "destination-atop", |
|||
"destination-in", "destination-out", "destination-over", "devanagari", |
|||
"disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted", |
|||
"double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", |
|||
"element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede", |
|||
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er", |
|||
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", |
|||
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et", |
|||
"ethiopic-halehame-gez", "ethiopic-halehame-om-et", |
|||
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et", |
|||
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", |
|||
"ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed", |
|||
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes", |
|||
"forwards", "from", "geometricPrecision", "georgian", "graytext", "groove", |
|||
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", |
|||
"help", "hidden", "hide", "higher", "highlight", "highlighttext", |
|||
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore", |
|||
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", |
|||
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis", |
|||
"inline-block", "inline-table", "inset", "inside", "intrinsic", "invert", |
|||
"italic", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer", |
|||
"landscape", "lao", "large", "larger", "left", "level", "lighter", |
|||
"line-through", "linear", "lines", "list-item", "listbox", "listitem", |
|||
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", |
|||
"lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian", |
|||
"lower-roman", "lowercase", "ltr", "malayalam", "match", |
|||
"media-controls-background", "media-current-time-display", |
|||
"media-fullscreen-button", "media-mute-button", "media-play-button", |
|||
"media-return-to-realtime-button", "media-rewind-button", |
|||
"media-seek-back-button", "media-seek-forward-button", "media-slider", |
|||
"media-sliderthumb", "media-time-remaining-display", "media-volume-slider", |
|||
"media-volume-slider-container", "media-volume-sliderthumb", "medium", |
|||
"menu", "menulist", "menulist-button", "menulist-text", |
|||
"menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", |
|||
"mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize", |
|||
"narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", |
|||
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap", |
|||
"ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote", |
|||
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset", |
|||
"outside", "outside-shape", "overlay", "overline", "padding", "padding-box", |
|||
"painted", "page", "paused", "persian", "plus-darker", "plus-lighter", "pointer", |
|||
"polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button", |
|||
"radio", "read-only", "read-write", "read-write-plaintext-only", "rectangle", "region", |
|||
"relative", "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba", |
|||
"ridge", "right", "round", "row-resize", "rtl", "run-in", "running", |
|||
"s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield", |
|||
"searchfield-cancel-button", "searchfield-decoration", |
|||
"searchfield-results-button", "searchfield-results-decoration", |
|||
"semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama", |
|||
"single", "skip-white-space", "slide", "slider-horizontal", |
|||
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", |
|||
"small", "small-caps", "small-caption", "smaller", "solid", "somali", |
|||
"source-atop", "source-in", "source-out", "source-over", "space", "square", |
|||
"square-button", "start", "static", "status-bar", "stretch", "stroke", |
|||
"sub", "subpixel-antialiased", "super", "sw-resize", "table", |
|||
"table-caption", "table-cell", "table-column", "table-column-group", |
|||
"table-footer-group", "table-header-group", "table-row", "table-row-group", |
|||
"telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai", |
|||
"thick", "thin", "threeddarkshadow", "threedface", "threedhighlight", |
|||
"threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er", |
|||
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top", |
|||
"transparent", "ultra-condensed", "ultra-expanded", "underline", "up", |
|||
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal", |
|||
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", |
|||
"vertical", "vertical-text", "visible", "visibleFill", "visiblePainted", |
|||
"visibleStroke", "visual", "w-resize", "wait", "wave", "wider", |
|||
"window", "windowframe", "windowtext", "x-large", "x-small", "xor", |
|||
"xx-large", "xx-small" |
|||
], valueKeywords = keySet(valueKeywords_); |
|||
|
|||
var fontProperties_ = [ |
|||
"font-family", "src", "unicode-range", "font-variant", "font-feature-settings", |
|||
"font-stretch", "font-weight", "font-style" |
|||
], fontProperties = keySet(fontProperties_); |
|||
|
|||
var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_) |
|||
.concat(nonStandardPropertyKeywords_).concat(colorKeywords_).concat(valueKeywords_); |
|||
CodeMirror.registerHelper("hintWords", "css", allWords); |
|||
|
|||
function tokenCComment(stream, state) { |
|||
var maybeEnd = false, ch; |
|||
while ((ch = stream.next()) != null) { |
|||
if (maybeEnd && ch == "/") { |
|||
state.tokenize = null; |
|||
break; |
|||
} |
|||
maybeEnd = (ch == "*"); |
|||
} |
|||
return ["comment", "comment"]; |
|||
} |
|||
|
|||
function tokenSGMLComment(stream, state) { |
|||
if (stream.skipTo("-->")) { |
|||
stream.match("-->"); |
|||
state.tokenize = null; |
|||
} else { |
|||
stream.skipToEnd(); |
|||
} |
|||
return ["comment", "comment"]; |
|||
} |
|||
|
|||
CodeMirror.defineMIME("text/css", { |
|||
mediaTypes: mediaTypes, |
|||
mediaFeatures: mediaFeatures, |
|||
propertyKeywords: propertyKeywords, |
|||
nonStandardPropertyKeywords: nonStandardPropertyKeywords, |
|||
colorKeywords: colorKeywords, |
|||
valueKeywords: valueKeywords, |
|||
fontProperties: fontProperties, |
|||
tokenHooks: { |
|||
"<": function(stream, state) { |
|||
if (!stream.match("!--")) return false; |
|||
state.tokenize = tokenSGMLComment; |
|||
return tokenSGMLComment(stream, state); |
|||
}, |
|||
"/": function(stream, state) { |
|||
if (!stream.eat("*")) return false; |
|||
state.tokenize = tokenCComment; |
|||
return tokenCComment(stream, state); |
|||
} |
|||
}, |
|||
name: "css" |
|||
}); |
|||
|
|||
CodeMirror.defineMIME("text/x-scss", { |
|||
mediaTypes: mediaTypes, |
|||
mediaFeatures: mediaFeatures, |
|||
propertyKeywords: propertyKeywords, |
|||
nonStandardPropertyKeywords: nonStandardPropertyKeywords, |
|||
colorKeywords: colorKeywords, |
|||
valueKeywords: valueKeywords, |
|||
fontProperties: fontProperties, |
|||
allowNested: true, |
|||
tokenHooks: { |
|||
"/": function(stream, state) { |
|||
if (stream.eat("/")) { |
|||
stream.skipToEnd(); |
|||
return ["comment", "comment"]; |
|||
} else if (stream.eat("*")) { |
|||
state.tokenize = tokenCComment; |
|||
return tokenCComment(stream, state); |
|||
} else { |
|||
return ["operator", "operator"]; |
|||
} |
|||
}, |
|||
":": function(stream) { |
|||
if (stream.match(/\s*\{/)) |
|||
return [null, "{"]; |
|||
return false; |
|||
}, |
|||
"$": function(stream) { |
|||
stream.match(/^[\w-]+/); |
|||
if (stream.match(/^\s*:/, false)) |
|||
return ["variable-2", "variable-definition"]; |
|||
return ["variable-2", "variable"]; |
|||
}, |
|||
"#": function(stream) { |
|||
if (!stream.eat("{")) return false; |
|||
return [null, "interpolation"]; |
|||
} |
|||
}, |
|||
name: "css", |
|||
helperType: "scss" |
|||
}); |
|||
|
|||
CodeMirror.defineMIME("text/x-less", { |
|||
mediaTypes: mediaTypes, |
|||
mediaFeatures: mediaFeatures, |
|||
propertyKeywords: propertyKeywords, |
|||
nonStandardPropertyKeywords: nonStandardPropertyKeywords, |
|||
colorKeywords: colorKeywords, |
|||
valueKeywords: valueKeywords, |
|||
fontProperties: fontProperties, |
|||
allowNested: true, |
|||
tokenHooks: { |
|||
"/": function(stream, state) { |
|||
if (stream.eat("/")) { |
|||
stream.skipToEnd(); |
|||
return ["comment", "comment"]; |
|||
} else if (stream.eat("*")) { |
|||
state.tokenize = tokenCComment; |
|||
return tokenCComment(stream, state); |
|||
} else { |
|||
return ["operator", "operator"]; |
|||
} |
|||
}, |
|||
"@": function(stream) { |
|||
if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false; |
|||
stream.eatWhile(/[\w\\\-]/); |
|||
if (stream.match(/^\s*:/, false)) |
|||
return ["variable-2", "variable-definition"]; |
|||
return ["variable-2", "variable"]; |
|||
}, |
|||
"&": function() { |
|||
return ["atom", "atom"]; |
|||
} |
|||
}, |
|||
name: "css", |
|||
helperType: "less" |
|||
}); |
|||
|
|||
}); |
@ -0,0 +1,6 @@ |
|||
.CodeMirror-fullscreen { |
|||
position: fixed; |
|||
top: 0; left: 0; right: 0; bottom: 0; |
|||
height: auto; |
|||
z-index: 9; |
|||
} |
@ -0,0 +1,41 @@ |
|||
// 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")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
"use strict"; |
|||
|
|||
CodeMirror.defineOption("fullScreen", false, function(cm, val, old) { |
|||
if (old == CodeMirror.Init) old = false; |
|||
if (!old == !val) return; |
|||
if (val) setFullscreen(cm); |
|||
else setNormal(cm); |
|||
}); |
|||
|
|||
function setFullscreen(cm) { |
|||
var wrap = cm.getWrapperElement(); |
|||
cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset, |
|||
width: wrap.style.width, height: wrap.style.height}; |
|||
wrap.style.width = ""; |
|||
wrap.style.height = "auto"; |
|||
wrap.className += " CodeMirror-fullscreen"; |
|||
document.documentElement.style.overflow = "hidden"; |
|||
cm.refresh(); |
|||
} |
|||
|
|||
function setNormal(cm) { |
|||
var wrap = cm.getWrapperElement(); |
|||
wrap.className = wrap.className.replace(/\s*CodeMirror-fullscreen\b/, ""); |
|||
document.documentElement.style.overflow = ""; |
|||
var info = cm.state.fullScreenRestore; |
|||
wrap.style.width = info.width; wrap.style.height = info.height; |
|||
window.scrollTo(info.scrollLeft, info.scrollTop); |
|||
cm.refresh(); |
|||
} |
|||
}); |
@ -0,0 +1,121 @@ |
|||
// 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("../javascript/javascript"), require("../css/css")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
"use strict"; |
|||
|
|||
CodeMirror.defineMode("htmlmixed", function(config, parserConfig) { |
|||
var htmlMode = CodeMirror.getMode(config, {name: "xml", |
|||
htmlMode: true, |
|||
multilineTagIndentFactor: parserConfig.multilineTagIndentFactor, |
|||
multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag}); |
|||
var cssMode = CodeMirror.getMode(config, "css"); |
|||
|
|||
var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes; |
|||
scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, |
|||
mode: CodeMirror.getMode(config, "javascript")}); |
|||
if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) { |
|||
var conf = scriptTypesConf[i]; |
|||
scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)}); |
|||
} |
|||
scriptTypes.push({matches: /./, |
|||
mode: CodeMirror.getMode(config, "text/plain")}); |
|||
|
|||
function html(stream, state) { |
|||
var tagName = state.htmlState.tagName; |
|||
if (tagName) tagName = tagName.toLowerCase(); |
|||
var style = htmlMode.token(stream, state.htmlState); |
|||
if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") { |
|||
// Script block: mode to change to depends on type attribute
|
|||
var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i); |
|||
scriptType = scriptType ? scriptType[1] : ""; |
|||
if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1); |
|||
for (var i = 0; i < scriptTypes.length; ++i) { |
|||
var tp = scriptTypes[i]; |
|||
if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) { |
|||
if (tp.mode) { |
|||
state.token = script; |
|||
state.localMode = tp.mode; |
|||
state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, "")); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
} else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") { |
|||
state.token = css; |
|||
state.localMode = cssMode; |
|||
state.localState = cssMode.startState(htmlMode.indent(state.htmlState, "")); |
|||
} |
|||
return style; |
|||
} |
|||
function maybeBackup(stream, pat, style) { |
|||
var cur = stream.current(); |
|||
var close = cur.search(pat), m; |
|||
if (close > -1) stream.backUp(cur.length - close); |
|||
else if (m = cur.match(/<\/?$/)) { |
|||
stream.backUp(cur.length); |
|||
if (!stream.match(pat, false)) stream.match(cur); |
|||
} |
|||
return style; |
|||
} |
|||
function script(stream, state) { |
|||
if (stream.match(/^<\/\s*script\s*>/i, false)) { |
|||
state.token = html; |
|||
state.localState = state.localMode = null; |
|||
return null; |
|||
} |
|||
return maybeBackup(stream, /<\/\s*script\s*>/, |
|||
state.localMode.token(stream, state.localState)); |
|||
} |
|||
function css(stream, state) { |
|||
if (stream.match(/^<\/\s*style\s*>/i, false)) { |
|||
state.token = html; |
|||
state.localState = state.localMode = null; |
|||
return null; |
|||
} |
|||
return maybeBackup(stream, /<\/\s*style\s*>/, |
|||
cssMode.token(stream, state.localState)); |
|||
} |
|||
|
|||
return { |
|||
startState: function() { |
|||
var state = htmlMode.startState(); |
|||
return {token: html, localMode: null, localState: null, htmlState: state}; |
|||
}, |
|||
|
|||
copyState: function(state) { |
|||
if (state.localState) |
|||
var local = CodeMirror.copyState(state.localMode, state.localState); |
|||
return {token: state.token, localMode: state.localMode, localState: local, |
|||
htmlState: CodeMirror.copyState(htmlMode, state.htmlState)}; |
|||
}, |
|||
|
|||
token: function(stream, state) { |
|||
return state.token(stream, state); |
|||
}, |
|||
|
|||
indent: function(state, textAfter) { |
|||
if (!state.localMode || /^\s*<\//.test(textAfter)) |
|||
return htmlMode.indent(state.htmlState, textAfter); |
|||
else if (state.localMode.indent) |
|||
return state.localMode.indent(state.localState, textAfter); |
|||
else |
|||
return CodeMirror.Pass; |
|||
}, |
|||
|
|||
innerMode: function(state) { |
|||
return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode}; |
|||
} |
|||
}; |
|||
}, "xml", "javascript", "css"); |
|||
|
|||
CodeMirror.defineMIME("text/html", "htmlmixed"); |
|||
|
|||
}); |
@ -0,0 +1,686 @@ |
|||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|||
|
|||
// TODO actually recognize syntax of TypeScript constructs
|
|||
|
|||
(function(mod) { |
|||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|||
mod(require("../../lib/codemirror")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
"use strict"; |
|||
|
|||
CodeMirror.defineMode("javascript", function(config, parserConfig) { |
|||
var indentUnit = config.indentUnit; |
|||
var statementIndent = parserConfig.statementIndent; |
|||
var jsonldMode = parserConfig.jsonld; |
|||
var jsonMode = parserConfig.json || jsonldMode; |
|||
var isTS = parserConfig.typescript; |
|||
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; |
|||
|
|||
// Tokenizer
|
|||
|
|||
var keywords = function(){ |
|||
function kw(type) {return {type: type, style: "keyword"};} |
|||
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); |
|||
var operator = kw("operator"), atom = {type: "atom", style: "atom"}; |
|||
|
|||
var jsKeywords = { |
|||
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, |
|||
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C, |
|||
"var": kw("var"), "const": kw("var"), "let": kw("var"), |
|||
"function": kw("function"), "catch": kw("catch"), |
|||
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), |
|||
"in": operator, "typeof": operator, "instanceof": operator, |
|||
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, |
|||
"this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"), |
|||
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C |
|||
}; |
|||
|
|||
// Extend the 'normal' keywords with the TypeScript language extensions
|
|||
if (isTS) { |
|||
var type = {type: "variable", style: "variable-3"}; |
|||
var tsKeywords = { |
|||
// object-like things
|
|||
"interface": kw("interface"), |
|||
"extends": kw("extends"), |
|||
"constructor": kw("constructor"), |
|||
|
|||
// scope modifiers
|
|||
"public": kw("public"), |
|||
"private": kw("private"), |
|||
"protected": kw("protected"), |
|||
"static": kw("static"), |
|||
|
|||
// types
|
|||
"string": type, "number": type, "bool": type, "any": type |
|||
}; |
|||
|
|||
for (var attr in tsKeywords) { |
|||
jsKeywords[attr] = tsKeywords[attr]; |
|||
} |
|||
} |
|||
|
|||
return jsKeywords; |
|||
}(); |
|||
|
|||
var isOperatorChar = /[+\-*&%=<>!?|~^]/; |
|||
var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/; |
|||
|
|||
function readRegexp(stream) { |
|||
var escaped = false, next, inSet = false; |
|||
while ((next = stream.next()) != null) { |
|||
if (!escaped) { |
|||
if (next == "/" && !inSet) return; |
|||
if (next == "[") inSet = true; |
|||
else if (inSet && next == "]") inSet = false; |
|||
} |
|||
escaped = !escaped && next == "\\"; |
|||
} |
|||
} |
|||
|
|||
// Used as scratch variables to communicate multiple values without
|
|||
// consing up tons of objects.
|
|||
var type, content; |
|||
function ret(tp, style, cont) { |
|||
type = tp; content = cont; |
|||
return style; |
|||
} |
|||
function tokenBase(stream, state) { |
|||
var ch = stream.next(); |
|||
if (ch == '"' || ch == "'") { |
|||
state.tokenize = tokenString(ch); |
|||
return state.tokenize(stream, state); |
|||
} else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { |
|||
return ret("number", "number"); |
|||
} else if (ch == "." && stream.match("..")) { |
|||
return ret("spread", "meta"); |
|||
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { |
|||
return ret(ch); |
|||
} else if (ch == "=" && stream.eat(">")) { |
|||
return ret("=>", "operator"); |
|||
} else if (ch == "0" && stream.eat(/x/i)) { |
|||
stream.eatWhile(/[\da-f]/i); |
|||
return ret("number", "number"); |
|||
} else if (/\d/.test(ch)) { |
|||
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); |
|||
return ret("number", "number"); |
|||
} else if (ch == "/") { |
|||
if (stream.eat("*")) { |
|||
state.tokenize = tokenComment; |
|||
return tokenComment(stream, state); |
|||
} else if (stream.eat("/")) { |
|||
stream.skipToEnd(); |
|||
return ret("comment", "comment"); |
|||
} else if (state.lastType == "operator" || state.lastType == "keyword c" || |
|||
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) { |
|||
readRegexp(stream); |
|||
stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
|
|||
return ret("regexp", "string-2"); |
|||
} else { |
|||
stream.eatWhile(isOperatorChar); |
|||
return ret("operator", "operator", stream.current()); |
|||
} |
|||
} else if (ch == "`") { |
|||
state.tokenize = tokenQuasi; |
|||
return tokenQuasi(stream, state); |
|||
} else if (ch == "#") { |
|||
stream.skipToEnd(); |
|||
return ret("error", "error"); |
|||
} else if (isOperatorChar.test(ch)) { |
|||
stream.eatWhile(isOperatorChar); |
|||
return ret("operator", "operator", stream.current()); |
|||
} else if (wordRE.test(ch)) { |
|||
stream.eatWhile(wordRE); |
|||
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; |
|||
return (known && state.lastType != ".") ? ret(known.type, known.style, word) : |
|||
ret("variable", "variable", word); |
|||
} |
|||
} |
|||
|
|||
function tokenString(quote) { |
|||
return function(stream, state) { |
|||
var escaped = false, next; |
|||
if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){ |
|||
state.tokenize = tokenBase; |
|||
return ret("jsonld-keyword", "meta"); |
|||
} |
|||
while ((next = stream.next()) != null) { |
|||
if (next == quote && !escaped) break; |
|||
escaped = !escaped && next == "\\"; |
|||
} |
|||
if (!escaped) state.tokenize = tokenBase; |
|||
return ret("string", "string"); |
|||
}; |
|||
} |
|||
|
|||
function tokenComment(stream, state) { |
|||
var maybeEnd = false, ch; |
|||
while (ch = stream.next()) { |
|||
if (ch == "/" && maybeEnd) { |
|||
state.tokenize = tokenBase; |
|||
break; |
|||
} |
|||
maybeEnd = (ch == "*"); |
|||
} |
|||
return ret("comment", "comment"); |
|||
} |
|||
|
|||
function tokenQuasi(stream, state) { |
|||
var escaped = false, next; |
|||
while ((next = stream.next()) != null) { |
|||
if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) { |
|||
state.tokenize = tokenBase; |
|||
break; |
|||
} |
|||
escaped = !escaped && next == "\\"; |
|||
} |
|||
return ret("quasi", "string-2", stream.current()); |
|||
} |
|||
|
|||
var brackets = "([{}])"; |
|||
// This is a crude lookahead trick to try and notice that we're
|
|||
// parsing the argument patterns for a fat-arrow function before we
|
|||
// actually hit the arrow token. It only works if the arrow is on
|
|||
// the same line as the arguments and there's no strange noise
|
|||
// (comments) in between. Fallback is to only notice when we hit the
|
|||
// arrow, and not declare the arguments as locals for the arrow
|
|||
// body.
|
|||
function findFatArrow(stream, state) { |
|||
if (state.fatArrowAt) state.fatArrowAt = null; |
|||
var arrow = stream.string.indexOf("=>", stream.start); |
|||
if (arrow < 0) return; |
|||
|
|||
var depth = 0, sawSomething = false; |
|||
for (var pos = arrow - 1; pos >= 0; --pos) { |
|||
var ch = stream.string.charAt(pos); |
|||
var bracket = brackets.indexOf(ch); |
|||
if (bracket >= 0 && bracket < 3) { |
|||
if (!depth) { ++pos; break; } |
|||
if (--depth == 0) break; |
|||
} else if (bracket >= 3 && bracket < 6) { |
|||
++depth; |
|||
} else if (wordRE.test(ch)) { |
|||
sawSomething = true; |
|||
} else if (/["'\/]/.test(ch)) { |
|||
return; |
|||
} else if (sawSomething && !depth) { |
|||
++pos; |
|||
break; |
|||
} |
|||
} |
|||
if (sawSomething && !depth) state.fatArrowAt = pos; |
|||
} |
|||
|
|||
// Parser
|
|||
|
|||
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true}; |
|||
|
|||
function JSLexical(indented, column, type, align, prev, info) { |
|||
this.indented = indented; |
|||
this.column = column; |
|||
this.type = type; |
|||
this.prev = prev; |
|||
this.info = info; |
|||
if (align != null) this.align = align; |
|||
} |
|||
|
|||
function inScope(state, varname) { |
|||
for (var v = state.localVars; v; v = v.next) |
|||
if (v.name == varname) return true; |
|||
for (var cx = state.context; cx; cx = cx.prev) { |
|||
for (var v = cx.vars; v; v = v.next) |
|||
if (v.name == varname) return true; |
|||
} |
|||
} |
|||
|
|||
function parseJS(state, style, type, content, stream) { |
|||
var cc = state.cc; |
|||
// Communicate our context to the combinators.
|
|||
// (Less wasteful than consing up a hundred closures on every call.)
|
|||
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style; |
|||
|
|||
if (!state.lexical.hasOwnProperty("align")) |
|||
state.lexical.align = true; |
|||
|
|||
while(true) { |
|||
var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; |
|||
if (combinator(type, content)) { |
|||
while(cc.length && cc[cc.length - 1].lex) |
|||
cc.pop()(); |
|||
if (cx.marked) return cx.marked; |
|||
if (type == "variable" && inScope(state, content)) return "variable-2"; |
|||
return style; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Combinator utils
|
|||
|
|||
var cx = {state: null, column: null, marked: null, cc: null}; |
|||
function pass() { |
|||
for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); |
|||
} |
|||
function cont() { |
|||
pass.apply(null, arguments); |
|||
return true; |
|||
} |
|||
function register(varname) { |
|||
function inList(list) { |
|||
for (var v = list; v; v = v.next) |
|||
if (v.name == varname) return true; |
|||
return false; |
|||
} |
|||
var state = cx.state; |
|||
if (state.context) { |
|||
cx.marked = "def"; |
|||
if (inList(state.localVars)) return; |
|||
state.localVars = {name: varname, next: state.localVars}; |
|||
} else { |
|||
if (inList(state.globalVars)) return; |
|||
if (parserConfig.globalVars) |
|||
state.globalVars = {name: varname, next: state.globalVars}; |
|||
} |
|||
} |
|||
|
|||
// Combinators
|
|||
|
|||
var defaultVars = {name: "this", next: {name: "arguments"}}; |
|||
function pushcontext() { |
|||
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; |
|||
cx.state.localVars = defaultVars; |
|||
} |
|||
function popcontext() { |
|||
cx.state.localVars = cx.state.context.vars; |
|||
cx.state.context = cx.state.context.prev; |
|||
} |
|||
function pushlex(type, info) { |
|||
var result = function() { |
|||
var state = cx.state, indent = state.indented; |
|||
if (state.lexical.type == "stat") indent = state.lexical.indented; |
|||
else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev) |
|||
indent = outer.indented; |
|||
state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info); |
|||
}; |
|||
result.lex = true; |
|||
return result; |
|||
} |
|||
function poplex() { |
|||
var state = cx.state; |
|||
if (state.lexical.prev) { |
|||
if (state.lexical.type == ")") |
|||
state.indented = state.lexical.indented; |
|||
state.lexical = state.lexical.prev; |
|||
} |
|||
} |
|||
poplex.lex = true; |
|||
|
|||
function expect(wanted) { |
|||
function exp(type) { |
|||
if (type == wanted) return cont(); |
|||
else if (wanted == ";") return pass(); |
|||
else return cont(exp); |
|||
}; |
|||
return exp; |
|||
} |
|||
|
|||
function statement(type, value) { |
|||
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); |
|||
if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); |
|||
if (type == "keyword b") return cont(pushlex("form"), statement, poplex); |
|||
if (type == "{") return cont(pushlex("}"), block, poplex); |
|||
if (type == ";") return cont(); |
|||
if (type == "if") { |
|||
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) |
|||
cx.state.cc.pop()(); |
|||
return cont(pushlex("form"), expression, statement, poplex, maybeelse); |
|||
} |
|||
if (type == "function") return cont(functiondef); |
|||
if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); |
|||
if (type == "variable") return cont(pushlex("stat"), maybelabel); |
|||
if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), |
|||
block, poplex, poplex); |
|||
if (type == "case") return cont(expression, expect(":")); |
|||
if (type == "default") return cont(expect(":")); |
|||
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), |
|||
statement, poplex, popcontext); |
|||
if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex); |
|||
if (type == "class") return cont(pushlex("form"), className, poplex); |
|||
if (type == "export") return cont(pushlex("form"), afterExport, poplex); |
|||
if (type == "import") return cont(pushlex("form"), afterImport, poplex); |
|||
return pass(pushlex("stat"), expression, expect(";"), poplex); |
|||
} |
|||
function expression(type) { |
|||
return expressionInner(type, false); |
|||
} |
|||
function expressionNoComma(type) { |
|||
return expressionInner(type, true); |
|||
} |
|||
function expressionInner(type, noComma) { |
|||
if (cx.state.fatArrowAt == cx.stream.start) { |
|||
var body = noComma ? arrowBodyNoComma : arrowBody; |
|||
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); |
|||
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); |
|||
} |
|||
|
|||
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; |
|||
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); |
|||
if (type == "function") return cont(functiondef, maybeop); |
|||
if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression); |
|||
if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop); |
|||
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); |
|||
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); |
|||
if (type == "{") return contCommasep(objprop, "}", null, maybeop); |
|||
if (type == "quasi") { return pass(quasi, maybeop); } |
|||
return cont(); |
|||
} |
|||
function maybeexpression(type) { |
|||
if (type.match(/[;\}\)\],]/)) return pass(); |
|||
return pass(expression); |
|||
} |
|||
function maybeexpressionNoComma(type) { |
|||
if (type.match(/[;\}\)\],]/)) return pass(); |
|||
return pass(expressionNoComma); |
|||
} |
|||
|
|||
function maybeoperatorComma(type, value) { |
|||
if (type == ",") return cont(expression); |
|||
return maybeoperatorNoComma(type, value, false); |
|||
} |
|||
function maybeoperatorNoComma(type, value, noComma) { |
|||
var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; |
|||
var expr = noComma == false ? expression : expressionNoComma; |
|||
if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); |
|||
if (type == "operator") { |
|||
if (/\+\+|--/.test(value)) return cont(me); |
|||
if (value == "?") return cont(expression, expect(":"), expr); |
|||
return cont(expr); |
|||
} |
|||
if (type == "quasi") { return pass(quasi, me); } |
|||
if (type == ";") return; |
|||
if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); |
|||
if (type == ".") return cont(property, me); |
|||
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); |
|||
} |
|||
function quasi(type, value) { |
|||
if (type != "quasi") return pass(); |
|||
if (value.slice(value.length - 2) != "${") return cont(quasi); |
|||
return cont(expression, continueQuasi); |
|||
} |
|||
function continueQuasi(type) { |
|||
if (type == "}") { |
|||
cx.marked = "string-2"; |
|||
cx.state.tokenize = tokenQuasi; |
|||
return cont(quasi); |
|||
} |
|||
} |
|||
function arrowBody(type) { |
|||
findFatArrow(cx.stream, cx.state); |
|||
return pass(type == "{" ? statement : expression); |
|||
} |
|||
function arrowBodyNoComma(type) { |
|||
findFatArrow(cx.stream, cx.state); |
|||
return pass(type == "{" ? statement : expressionNoComma); |
|||
} |
|||
function maybelabel(type) { |
|||
if (type == ":") return cont(poplex, statement); |
|||
return pass(maybeoperatorComma, expect(";"), poplex); |
|||
} |
|||
function property(type) { |
|||
if (type == "variable") {cx.marked = "property"; return cont();} |
|||
} |
|||
function objprop(type, value) { |
|||
if (type == "variable" || cx.style == "keyword") { |
|||
cx.marked = "property"; |
|||
if (value == "get" || value == "set") return cont(getterSetter); |
|||
return cont(afterprop); |
|||
} else if (type == "number" || type == "string") { |
|||
cx.marked = jsonldMode ? "property" : (cx.style + " property"); |
|||
return cont(afterprop); |
|||
} else if (type == "jsonld-keyword") { |
|||
return cont(afterprop); |
|||
} else if (type == "[") { |
|||
return cont(expression, expect("]"), afterprop); |
|||
} |
|||
} |
|||
function getterSetter(type) { |
|||
if (type != "variable") return pass(afterprop); |
|||
cx.marked = "property"; |
|||
return cont(functiondef); |
|||
} |
|||
function afterprop(type) { |
|||
if (type == ":") return cont(expressionNoComma); |
|||
if (type == "(") return pass(functiondef); |
|||
} |
|||
function commasep(what, end) { |
|||
function proceed(type) { |
|||
if (type == ",") { |
|||
var lex = cx.state.lexical; |
|||
if (lex.info == "call") lex.pos = (lex.pos || 0) + 1; |
|||
return cont(what, proceed); |
|||
} |
|||
if (type == end) return cont(); |
|||
return cont(expect(end)); |
|||
} |
|||
return function(type) { |
|||
if (type == end) return cont(); |
|||
return pass(what, proceed); |
|||
}; |
|||
} |
|||
function contCommasep(what, end, info) { |
|||
for (var i = 3; i < arguments.length; i++) |
|||
cx.cc.push(arguments[i]); |
|||
return cont(pushlex(end, info), commasep(what, end), poplex); |
|||
} |
|||
function block(type) { |
|||
if (type == "}") return cont(); |
|||
return pass(statement, block); |
|||
} |
|||
function maybetype(type) { |
|||
if (isTS && type == ":") return cont(typedef); |
|||
} |
|||
function typedef(type) { |
|||
if (type == "variable"){cx.marked = "variable-3"; return cont();} |
|||
} |
|||
function vardef() { |
|||
return pass(pattern, maybetype, maybeAssign, vardefCont); |
|||
} |
|||
function pattern(type, value) { |
|||
if (type == "variable") { register(value); return cont(); } |
|||
if (type == "[") return contCommasep(pattern, "]"); |
|||
if (type == "{") return contCommasep(proppattern, "}"); |
|||
} |
|||
function proppattern(type, value) { |
|||
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { |
|||
register(value); |
|||
return cont(maybeAssign); |
|||
} |
|||
if (type == "variable") cx.marked = "property"; |
|||
return cont(expect(":"), pattern, maybeAssign); |
|||
} |
|||
function maybeAssign(_type, value) { |
|||
if (value == "=") return cont(expressionNoComma); |
|||
} |
|||
function vardefCont(type) { |
|||
if (type == ",") return cont(vardef); |
|||
} |
|||
function maybeelse(type, value) { |
|||
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex); |
|||
} |
|||
function forspec(type) { |
|||
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); |
|||
} |
|||
function forspec1(type) { |
|||
if (type == "var") return cont(vardef, expect(";"), forspec2); |
|||
if (type == ";") return cont(forspec2); |
|||
if (type == "variable") return cont(formaybeinof); |
|||
return pass(expression, expect(";"), forspec2); |
|||
} |
|||
function formaybeinof(_type, value) { |
|||
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } |
|||
return cont(maybeoperatorComma, forspec2); |
|||
} |
|||
function forspec2(type, value) { |
|||
if (type == ";") return cont(forspec3); |
|||
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } |
|||
return pass(expression, expect(";"), forspec3); |
|||
} |
|||
function forspec3(type) { |
|||
if (type != ")") cont(expression); |
|||
} |
|||
function functiondef(type, value) { |
|||
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} |
|||
if (type == "variable") {register(value); return cont(functiondef);} |
|||
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext); |
|||
} |
|||
function funarg(type) { |
|||
if (type == "spread") return cont(funarg); |
|||
return pass(pattern, maybetype); |
|||
} |
|||
function className(type, value) { |
|||
if (type == "variable") {register(value); return cont(classNameAfter);} |
|||
} |
|||
function classNameAfter(type, value) { |
|||
if (value == "extends") return cont(expression, classNameAfter); |
|||
if (type == "{") return cont(pushlex("}"), classBody, poplex); |
|||
} |
|||
function classBody(type, value) { |
|||
if (type == "variable" || cx.style == "keyword") { |
|||
cx.marked = "property"; |
|||
if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody); |
|||
return cont(functiondef, classBody); |
|||
} |
|||
if (value == "*") { |
|||
cx.marked = "keyword"; |
|||
return cont(classBody); |
|||
} |
|||
if (type == ";") return cont(classBody); |
|||
if (type == "}") return cont(); |
|||
} |
|||
function classGetterSetter(type) { |
|||
if (type != "variable") return pass(); |
|||
cx.marked = "property"; |
|||
return cont(); |
|||
} |
|||
function afterModule(type, value) { |
|||
if (type == "string") return cont(statement); |
|||
if (type == "variable") { register(value); return cont(maybeFrom); } |
|||
} |
|||
function afterExport(_type, value) { |
|||
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); } |
|||
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); } |
|||
return pass(statement); |
|||
} |
|||
function afterImport(type) { |
|||
if (type == "string") return cont(); |
|||
return pass(importSpec, maybeFrom); |
|||
} |
|||
function importSpec(type, value) { |
|||
if (type == "{") return contCommasep(importSpec, "}"); |
|||
if (type == "variable") register(value); |
|||
return cont(); |
|||
} |
|||
function maybeFrom(_type, value) { |
|||
if (value == "from") { cx.marked = "keyword"; return cont(expression); } |
|||
} |
|||
function arrayLiteral(type) { |
|||
if (type == "]") return cont(); |
|||
return pass(expressionNoComma, maybeArrayComprehension); |
|||
} |
|||
function maybeArrayComprehension(type) { |
|||
if (type == "for") return pass(comprehension, expect("]")); |
|||
if (type == ",") return cont(commasep(maybeexpressionNoComma, "]")); |
|||
return pass(commasep(expressionNoComma, "]")); |
|||
} |
|||
function comprehension(type) { |
|||
if (type == "for") return cont(forspec, comprehension); |
|||
if (type == "if") return cont(expression, comprehension); |
|||
} |
|||
|
|||
// Interface
|
|||
|
|||
return { |
|||
startState: function(basecolumn) { |
|||
var state = { |
|||
tokenize: tokenBase, |
|||
lastType: "sof", |
|||
cc: [], |
|||
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), |
|||
localVars: parserConfig.localVars, |
|||
context: parserConfig.localVars && {vars: parserConfig.localVars}, |
|||
indented: 0 |
|||
}; |
|||
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") |
|||
state.globalVars = parserConfig.globalVars; |
|||
return state; |
|||
}, |
|||
|
|||
token: function(stream, state) { |
|||
if (stream.sol()) { |
|||
if (!state.lexical.hasOwnProperty("align")) |
|||
state.lexical.align = false; |
|||
state.indented = stream.indentation(); |
|||
findFatArrow(stream, state); |
|||
} |
|||
if (state.tokenize != tokenComment && stream.eatSpace()) return null; |
|||
var style = state.tokenize(stream, state); |
|||
if (type == "comment") return style; |
|||
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type; |
|||
return parseJS(state, style, type, content, stream); |
|||
}, |
|||
|
|||
indent: function(state, textAfter) { |
|||
if (state.tokenize == tokenComment) return CodeMirror.Pass; |
|||
if (state.tokenize != tokenBase) return 0; |
|||
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; |
|||
// Kludge to prevent 'maybelse' from blocking lexical scope pops
|
|||
if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { |
|||
var c = state.cc[i]; |
|||
if (c == poplex) lexical = lexical.prev; |
|||
else if (c != maybeelse) break; |
|||
} |
|||
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; |
|||
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") |
|||
lexical = lexical.prev; |
|||
var type = lexical.type, closing = firstChar == type; |
|||
|
|||
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); |
|||
else if (type == "form" && firstChar == "{") return lexical.indented; |
|||
else if (type == "form") return lexical.indented + indentUnit; |
|||
else if (type == "stat") |
|||
return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? statementIndent || indentUnit : 0); |
|||
else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false) |
|||
return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); |
|||
else if (lexical.align) return lexical.column + (closing ? 0 : 1); |
|||
else return lexical.indented + (closing ? 0 : indentUnit); |
|||
}, |
|||
|
|||
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, |
|||
blockCommentStart: jsonMode ? null : "/*", |
|||
blockCommentEnd: jsonMode ? null : "*/", |
|||
lineComment: jsonMode ? null : "//", |
|||
fold: "brace", |
|||
|
|||
helperType: jsonMode ? "json" : "javascript", |
|||
jsonldMode: jsonldMode, |
|||
jsonMode: jsonMode |
|||
}; |
|||
}); |
|||
|
|||
CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/); |
|||
|
|||
CodeMirror.defineMIME("text/javascript", "javascript"); |
|||
CodeMirror.defineMIME("text/ecmascript", "javascript"); |
|||
CodeMirror.defineMIME("application/javascript", "javascript"); |
|||
CodeMirror.defineMIME("application/x-javascript", "javascript"); |
|||
CodeMirror.defineMIME("application/ecmascript", "javascript"); |
|||
CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); |
|||
CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); |
|||
CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true}); |
|||
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); |
|||
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); |
|||
|
|||
}); |
@ -0,0 +1,120 @@ |
|||
// 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")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && |
|||
(document.documentMode == null || document.documentMode < 8); |
|||
|
|||
var Pos = CodeMirror.Pos; |
|||
|
|||
var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; |
|||
|
|||
function findMatchingBracket(cm, where, strict, config) { |
|||
var line = cm.getLineHandle(where.line), pos = where.ch - 1; |
|||
var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; |
|||
if (!match) return null; |
|||
var dir = match.charAt(1) == ">" ? 1 : -1; |
|||
if (strict && (dir > 0) != (pos == where.ch)) return null; |
|||
var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); |
|||
|
|||
var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config); |
|||
if (found == null) return null; |
|||
return {from: Pos(where.line, pos), to: found && found.pos, |
|||
match: found && found.ch == match.charAt(0), forward: dir > 0}; |
|||
} |
|||
|
|||
// bracketRegex is used to specify which type of bracket to scan
|
|||
// should be a regexp, e.g. /[[\]]/
|
|||
//
|
|||
// Note: If "where" is on an open bracket, then this bracket is ignored.
|
|||
//
|
|||
// Returns false when no bracket was found, null when it reached
|
|||
// maxScanLines and gave up
|
|||
function scanForBracket(cm, where, dir, style, config) { |
|||
var maxScanLen = (config && config.maxScanLineLength) || 10000; |
|||
var maxScanLines = (config && config.maxScanLines) || 1000; |
|||
|
|||
var stack = []; |
|||
var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/; |
|||
var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) |
|||
: Math.max(cm.firstLine() - 1, where.line - maxScanLines); |
|||
for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { |
|||
var line = cm.getLine(lineNo); |
|||
if (!line) continue; |
|||
var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1; |
|||
if (line.length > maxScanLen) continue; |
|||
if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0); |
|||
for (; pos != end; pos += dir) { |
|||
var ch = line.charAt(pos); |
|||
if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) { |
|||
var match = matching[ch]; |
|||
if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch); |
|||
else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch}; |
|||
else stack.pop(); |
|||
} |
|||
} |
|||
} |
|||
return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null; |
|||
} |
|||
|
|||
function matchBrackets(cm, autoclear, config) { |
|||
// Disable brace matching in long lines, since it'll cause hugely slow updates
|
|||
var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000; |
|||
var marks = [], ranges = cm.listSelections(); |
|||
for (var i = 0; i < ranges.length; i++) { |
|||
var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config); |
|||
if (match && cm.getLine(match.from.line).length <= maxHighlightLen) { |
|||
var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; |
|||
marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style})); |
|||
if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen) |
|||
marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style})); |
|||
} |
|||
} |
|||
|
|||
if (marks.length) { |
|||
// Kludge to work around the IE bug from issue #1193, where text
|
|||
// input stops going to the textare whever this fires.
|
|||
if (ie_lt8 && cm.state.focused) cm.display.input.focus(); |
|||
|
|||
var clear = function() { |
|||
cm.operation(function() { |
|||
for (var i = 0; i < marks.length; i++) marks[i].clear(); |
|||
}); |
|||
}; |
|||
if (autoclear) setTimeout(clear, 800); |
|||
else return clear; |
|||
} |
|||
} |
|||
|
|||
var currentlyHighlighted = null; |
|||
function doMatchBrackets(cm) { |
|||
cm.operation(function() { |
|||
if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} |
|||
currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets); |
|||
}); |
|||
} |
|||
|
|||
CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { |
|||
if (old && old != CodeMirror.Init) |
|||
cm.off("cursorActivity", doMatchBrackets); |
|||
if (val) { |
|||
cm.state.matchBrackets = typeof val == "object" ? val : {}; |
|||
cm.on("cursorActivity", doMatchBrackets); |
|||
} |
|||
}); |
|||
|
|||
CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); |
|||
CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){ |
|||
return findMatchingBracket(this, pos, strict, config); |
|||
}); |
|||
CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){ |
|||
return scanForBracket(this, pos, dir, style, config); |
|||
}); |
|||
}); |
@ -0,0 +1,165 @@ |
|||
/* |
|||
Solarized theme for code-mirror |
|||
http://ethanschoonover.com/solarized |
|||
*/ |
|||
|
|||
/* |
|||
Solarized color pallet |
|||
http://ethanschoonover.com/solarized/img/solarized-palette.png |
|||
*/ |
|||
|
|||
.solarized.base03 { color: #002b36; } |
|||
.solarized.base02 { color: #073642; } |
|||
.solarized.base01 { color: #586e75; } |
|||
.solarized.base00 { color: #657b83; } |
|||
.solarized.base0 { color: #839496; } |
|||
.solarized.base1 { color: #93a1a1; } |
|||
.solarized.base2 { color: #eee8d5; } |
|||
.solarized.base3 { color: #fdf6e3; } |
|||
.solarized.solar-yellow { color: #b58900; } |
|||
.solarized.solar-orange { color: #cb4b16; } |
|||
.solarized.solar-red { color: #dc322f; } |
|||
.solarized.solar-magenta { color: #d33682; } |
|||
.solarized.solar-violet { color: #6c71c4; } |
|||
.solarized.solar-blue { color: #268bd2; } |
|||
.solarized.solar-cyan { color: #2aa198; } |
|||
.solarized.solar-green { color: #859900; } |
|||
|
|||
/* Color scheme for code-mirror */ |
|||
|
|||
.cm-s-solarized { |
|||
line-height: 1.45em; |
|||
color-profile: sRGB; |
|||
rendering-intent: auto; |
|||
} |
|||
.cm-s-solarized.cm-s-dark { |
|||
color: #839496; |
|||
background-color: #002b36; |
|||
text-shadow: #002b36 0 1px; |
|||
} |
|||
.cm-s-solarized.cm-s-light { |
|||
background-color: #fdf6e3; |
|||
color: #657b83; |
|||
text-shadow: #eee8d5 0 1px; |
|||
} |
|||
|
|||
.cm-s-solarized .CodeMirror-widget { |
|||
text-shadow: none; |
|||
} |
|||
|
|||
|
|||
.cm-s-solarized .cm-keyword { color: #cb4b16 } |
|||
.cm-s-solarized .cm-atom { color: #d33682; } |
|||
.cm-s-solarized .cm-number { color: #d33682; } |
|||
.cm-s-solarized .cm-def { color: #2aa198; } |
|||
|
|||
.cm-s-solarized .cm-variable { color: #268bd2; } |
|||
.cm-s-solarized .cm-variable-2 { color: #b58900; } |
|||
.cm-s-solarized .cm-variable-3 { color: #6c71c4; } |
|||
|
|||
.cm-s-solarized .cm-property { color: #2aa198; } |
|||
.cm-s-solarized .cm-operator {color: #6c71c4;} |
|||
|
|||
.cm-s-solarized .cm-comment { color: #586e75; font-style:italic; } |
|||
|
|||
.cm-s-solarized .cm-string { color: #859900; } |
|||
.cm-s-solarized .cm-string-2 { color: #b58900; } |
|||
|
|||
.cm-s-solarized .cm-meta { color: #859900; } |
|||
.cm-s-solarized .cm-qualifier { color: #b58900; } |
|||
.cm-s-solarized .cm-builtin { color: #d33682; } |
|||
.cm-s-solarized .cm-bracket { color: #cb4b16; } |
|||
.cm-s-solarized .CodeMirror-matchingbracket { color: #859900; } |
|||
.cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; } |
|||
.cm-s-solarized .cm-tag { color: #93a1a1 } |
|||
.cm-s-solarized .cm-attribute { color: #2aa198; } |
|||
.cm-s-solarized .cm-header { color: #586e75; } |
|||
.cm-s-solarized .cm-quote { color: #93a1a1; } |
|||
.cm-s-solarized .cm-hr { |
|||
color: transparent; |
|||
border-top: 1px solid #586e75; |
|||
display: block; |
|||
} |
|||
.cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; } |
|||
.cm-s-solarized .cm-special { color: #6c71c4; } |
|||
.cm-s-solarized .cm-em { |
|||
color: #999; |
|||
text-decoration: underline; |
|||
text-decoration-style: dotted; |
|||
} |
|||
.cm-s-solarized .cm-strong { color: #eee; } |
|||
.cm-s-solarized .cm-error, |
|||
.cm-s-solarized .cm-invalidchar { |
|||
color: #586e75; |
|||
border-bottom: 1px dotted #dc322f; |
|||
} |
|||
|
|||
.cm-s-solarized.cm-s-dark .CodeMirror-selected { |
|||
background: #073642; |
|||
} |
|||
|
|||
.cm-s-solarized.cm-s-light .CodeMirror-selected { |
|||
background: #eee8d5; |
|||
} |
|||
|
|||
/* Editor styling */ |
|||
|
|||
|
|||
|
|||
/* Little shadow on the view-port of the buffer view */ |
|||
.cm-s-solarized.CodeMirror { |
|||
-moz-box-shadow: inset 7px 0 12px -6px #000; |
|||
-webkit-box-shadow: inset 7px 0 12px -6px #000; |
|||
box-shadow: inset 7px 0 12px -6px #000; |
|||
} |
|||
|
|||
/* Gutter border and some shadow from it */ |
|||
.cm-s-solarized .CodeMirror-gutters { |
|||
border-right: 1px solid; |
|||
} |
|||
|
|||
/* Gutter colors and line number styling based of color scheme (dark / light) */ |
|||
|
|||
/* Dark */ |
|||
.cm-s-solarized.cm-s-dark .CodeMirror-gutters { |
|||
background-color: #002b36; |
|||
border-color: #00232c; |
|||
} |
|||
|
|||
.cm-s-solarized.cm-s-dark .CodeMirror-linenumber { |
|||
text-shadow: #021014 0 -1px; |
|||
} |
|||
|
|||
/* Light */ |
|||
.cm-s-solarized.cm-s-light .CodeMirror-gutters { |
|||
background-color: #fdf6e3; |
|||
border-color: #eee8d5; |
|||
} |
|||
|
|||
/* Common */ |
|||
.cm-s-solarized .CodeMirror-linenumber { |
|||
color: #586e75; |
|||
padding: 0 5px; |
|||
} |
|||
.cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; } |
|||
.cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; } |
|||
.cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; } |
|||
|
|||
.cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text { |
|||
color: #586e75; |
|||
} |
|||
|
|||
.cm-s-solarized .CodeMirror-lines .CodeMirror-cursor { |
|||
border-left: 1px solid #819090; |
|||
} |
|||
|
|||
/* |
|||
Active line. Negative margin compensates left padding of the text in the |
|||
view-port |
|||
*/ |
|||
.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background { |
|||
background: rgba(255, 255, 255, 0.10); |
|||
} |
|||
.cm-s-solarized.cm-s-light .CodeMirror-activeline-background { |
|||
background: rgba(0, 0, 0, 0.10); |
|||
} |
@ -0,0 +1,181 @@ |
|||
// based on go module
|
|||
(function(mod) { |
|||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|||
mod(require("../../lib/codemirror")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
"use strict"; |
|||
|
|||
CodeMirror.defineMode("solidity", function(config) { |
|||
var indentUnit = config.indentUnit; |
|||
|
|||
var keywords = { "delete":true, "break":true, "case":true, "const":true, "continue":true, "contract":true, "default":true, |
|||
"do":true, "else":true, "is":true, "for":true, "function":true, "if":true, "import":true, "mapping":true, "new":true, |
|||
"public":true, "private":true, "return":true, "returns":true, "struct":true, "switch":true, "var":true, "while":true, |
|||
"int":true, "uint":true, "hash":true, "bool":true, "string":true, "string0":true, "text":true, "real":true, |
|||
"ureal":true, |
|||
}; |
|||
|
|||
for (var i = 1; i <= 32; i++) { |
|||
keywords["int" + i * 8] = true; |
|||
keywords["uint" + i * 8] = true; |
|||
keywords["hash" + i * 8] = true; |
|||
keywords["string" + i] = true; |
|||
}; |
|||
|
|||
var atoms = { |
|||
"true":true, "false":true, "null":true |
|||
}; |
|||
|
|||
var isOperatorChar = /[+\-*&^%:=<>!|\/]/; |
|||
|
|||
var curPunc; |
|||
|
|||
function tokenBase(stream, state) { |
|||
var ch = stream.next(); |
|||
if (ch == '"' || ch == "'" || ch == "`") { |
|||
state.tokenize = tokenString(ch); |
|||
return state.tokenize(stream, state); |
|||
} |
|||
if (/[\d\.]/.test(ch)) { |
|||
if (ch == ".") { |
|||
stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/); |
|||
} else if (ch == "0") { |
|||
stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/); |
|||
} else { |
|||
stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/); |
|||
} |
|||
return "number"; |
|||
} |
|||
if (/[\[\]{}\(\),;\:\.]/.test(ch)) { |
|||
curPunc = ch; |
|||
return null; |
|||
} |
|||
if (ch == "/") { |
|||
if (stream.eat("*")) { |
|||
state.tokenize = tokenComment; |
|||
return tokenComment(stream, state); |
|||
} |
|||
if (stream.eat("/")) { |
|||
stream.skipToEnd(); |
|||
return "comment"; |
|||
} |
|||
} |
|||
if (isOperatorChar.test(ch)) { |
|||
stream.eatWhile(isOperatorChar); |
|||
return "operator"; |
|||
} |
|||
stream.eatWhile(/[\w\$_\xa1-\uffff]/); |
|||
var cur = stream.current(); |
|||
if (keywords.propertyIsEnumerable(cur)) { |
|||
if (cur == "case" || cur == "default") curPunc = "case"; |
|||
return "keyword"; |
|||
} |
|||
if (atoms.propertyIsEnumerable(cur)) return "atom"; |
|||
return "variable"; |
|||
} |
|||
|
|||
function tokenString(quote) { |
|||
return function(stream, state) { |
|||
var escaped = false, next, end = false; |
|||
while ((next = stream.next()) != null) { |
|||
if (next == quote && !escaped) {end = true; break;} |
|||
escaped = !escaped && next == "\\"; |
|||
} |
|||
if (end || !(escaped || quote == "`")) |
|||
state.tokenize = tokenBase; |
|||
return "string"; |
|||
}; |
|||
} |
|||
|
|||
function tokenComment(stream, state) { |
|||
var maybeEnd = false, ch; |
|||
while (ch = stream.next()) { |
|||
if (ch == "/" && maybeEnd) { |
|||
state.tokenize = tokenBase; |
|||
break; |
|||
} |
|||
maybeEnd = (ch == "*"); |
|||
} |
|||
return "comment"; |
|||
} |
|||
|
|||
function Context(indented, column, type, align, prev) { |
|||
this.indented = indented; |
|||
this.column = column; |
|||
this.type = type; |
|||
this.align = align; |
|||
this.prev = prev; |
|||
} |
|||
function pushContext(state, col, type) { |
|||
return state.context = new Context(state.indented, col, type, null, state.context); |
|||
} |
|||
function popContext(state) { |
|||
var t = state.context.type; |
|||
if (t == ")" || t == "]" || t == "}") |
|||
state.indented = state.context.indented; |
|||
return state.context = state.context.prev; |
|||
} |
|||
|
|||
// Interface
|
|||
|
|||
return { |
|||
startState: function(basecolumn) { |
|||
return { |
|||
tokenize: null, |
|||
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), |
|||
indented: 0, |
|||
startOfLine: true |
|||
}; |
|||
}, |
|||
|
|||
token: function(stream, state) { |
|||
var ctx = state.context; |
|||
if (stream.sol()) { |
|||
if (ctx.align == null) ctx.align = false; |
|||
state.indented = stream.indentation(); |
|||
state.startOfLine = true; |
|||
if (ctx.type == "case") ctx.type = "}"; |
|||
} |
|||
if (stream.eatSpace()) return null; |
|||
curPunc = null; |
|||
var style = (state.tokenize || tokenBase)(stream, state); |
|||
if (style == "comment") return style; |
|||
if (ctx.align == null) ctx.align = true; |
|||
|
|||
if (curPunc == "{") pushContext(state, stream.column(), "}"); |
|||
else if (curPunc == "[") pushContext(state, stream.column(), "]"); |
|||
else if (curPunc == "(") pushContext(state, stream.column(), ")"); |
|||
else if (curPunc == "case") ctx.type = "case"; |
|||
else if (curPunc == "}" && ctx.type == "}") ctx = popContext(state); |
|||
else if (curPunc == ctx.type) popContext(state); |
|||
state.startOfLine = false; |
|||
return style; |
|||
}, |
|||
|
|||
indent: function(state, textAfter) { |
|||
if (state.tokenize != tokenBase && state.tokenize != null) return 0; |
|||
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); |
|||
if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) { |
|||
state.context.type = "}"; |
|||
return ctx.indented; |
|||
} |
|||
var closing = firstChar == ctx.type; |
|||
if (ctx.align) return ctx.column + (closing ? 0 : 1); |
|||
else return ctx.indented + (closing ? 0 : indentUnit); |
|||
}, |
|||
|
|||
electricChars: "{}):", |
|||
fold: "brace", |
|||
blockCommentStart: "/*", |
|||
blockCommentEnd: "*/", |
|||
lineComment: "//" |
|||
}; |
|||
}); |
|||
|
|||
CodeMirror.defineMIME("text/x-solidity", "solidity"); |
|||
|
|||
}); |
@ -0,0 +1,384 @@ |
|||
// 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")); |
|||
else if (typeof define == "function" && define.amd) // AMD
|
|||
define(["../../lib/codemirror"], mod); |
|||
else // Plain browser env
|
|||
mod(CodeMirror); |
|||
})(function(CodeMirror) { |
|||
"use strict"; |
|||
|
|||
CodeMirror.defineMode("xml", function(config, parserConfig) { |
|||
var indentUnit = config.indentUnit; |
|||
var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1; |
|||
var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag; |
|||
if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true; |
|||
|
|||
var Kludges = parserConfig.htmlMode ? { |
|||
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, |
|||
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, |
|||
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, |
|||
'track': true, 'wbr': true, 'menuitem': true}, |
|||
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, |
|||
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, |
|||
'th': true, 'tr': true}, |
|||
contextGrabbers: { |
|||
'dd': {'dd': true, 'dt': true}, |
|||
'dt': {'dd': true, 'dt': true}, |
|||
'li': {'li': true}, |
|||
'option': {'option': true, 'optgroup': true}, |
|||
'optgroup': {'optgroup': true}, |
|||
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, |
|||
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, |
|||
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, |
|||
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, |
|||
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, |
|||
'rp': {'rp': true, 'rt': true}, |
|||
'rt': {'rp': true, 'rt': true}, |
|||
'tbody': {'tbody': true, 'tfoot': true}, |
|||
'td': {'td': true, 'th': true}, |
|||
'tfoot': {'tbody': true}, |
|||
'th': {'td': true, 'th': true}, |
|||
'thead': {'tbody': true, 'tfoot': true}, |
|||
'tr': {'tr': true} |
|||
}, |
|||
doNotIndent: {"pre": true}, |
|||
allowUnquoted: true, |
|||
allowMissing: true, |
|||
caseFold: true |
|||
} : { |
|||
autoSelfClosers: {}, |
|||
implicitlyClosed: {}, |
|||
contextGrabbers: {}, |
|||
doNotIndent: {}, |
|||
allowUnquoted: false, |
|||
allowMissing: false, |
|||
caseFold: false |
|||
}; |
|||
var alignCDATA = parserConfig.alignCDATA; |
|||
|
|||
// Return variables for tokenizers
|
|||
var type, setStyle; |
|||
|
|||
function inText(stream, state) { |
|||
function chain(parser) { |
|||
state.tokenize = parser; |
|||
return parser(stream, state); |
|||
} |
|||
|
|||
var ch = stream.next(); |
|||
if (ch == "<") { |
|||
if (stream.eat("!")) { |
|||
if (stream.eat("[")) { |
|||
if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); |
|||
else return null; |
|||
} else if (stream.match("--")) { |
|||
return chain(inBlock("comment", "-->")); |
|||
} else if (stream.match("DOCTYPE", true, true)) { |
|||
stream.eatWhile(/[\w\._\-]/); |
|||
return chain(doctype(1)); |
|||
} else { |
|||
return null; |
|||
} |
|||
} else if (stream.eat("?")) { |
|||
stream.eatWhile(/[\w\._\-]/); |
|||
state.tokenize = inBlock("meta", "?>"); |
|||
return "meta"; |
|||
} else { |
|||
type = stream.eat("/") ? "closeTag" : "openTag"; |
|||
state.tokenize = inTag; |
|||
return "tag bracket"; |
|||
} |
|||
} else if (ch == "&") { |
|||
var ok; |
|||
if (stream.eat("#")) { |
|||
if (stream.eat("x")) { |
|||
ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";"); |
|||
} else { |
|||
ok = stream.eatWhile(/[\d]/) && stream.eat(";"); |
|||
} |
|||
} else { |
|||
ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";"); |
|||
} |
|||
return ok ? "atom" : "error"; |
|||
} else { |
|||
stream.eatWhile(/[^&<]/); |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
function inTag(stream, state) { |
|||
var ch = stream.next(); |
|||
if (ch == ">" || (ch == "/" && stream.eat(">"))) { |
|||
state.tokenize = inText; |
|||
type = ch == ">" ? "endTag" : "selfcloseTag"; |
|||
return "tag bracket"; |
|||
} else if (ch == "=") { |
|||
type = "equals"; |
|||
return null; |
|||
} else if (ch == "<") { |
|||
state.tokenize = inText; |
|||
state.state = baseState; |
|||
state.tagName = state.tagStart = null; |
|||
var next = state.tokenize(stream, state); |
|||
return next ? next + " tag error" : "tag error"; |
|||
} else if (/[\'\"]/.test(ch)) { |
|||
state.tokenize = inAttribute(ch); |
|||
state.stringStartCol = stream.column(); |
|||
return state.tokenize(stream, state); |
|||
} else { |
|||
stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/); |
|||
return "word"; |
|||
} |
|||
} |
|||
|
|||
function inAttribute(quote) { |
|||
var closure = function(stream, state) { |
|||
while (!stream.eol()) { |
|||
if (stream.next() == quote) { |
|||
state.tokenize = inTag; |
|||
break; |
|||
} |
|||
} |
|||
return "string"; |
|||
}; |
|||
closure.isInAttribute = true; |
|||
return closure; |
|||
} |
|||
|
|||
function inBlock(style, terminator) { |
|||
return function(stream, state) { |
|||
while (!stream.eol()) { |
|||
if (stream.match(terminator)) { |
|||
state.tokenize = inText; |
|||
break; |
|||
} |
|||
stream.next(); |
|||
} |
|||
return style; |
|||
}; |
|||
} |
|||
function doctype(depth) { |
|||
return function(stream, state) { |
|||
var ch; |
|||
while ((ch = stream.next()) != null) { |
|||
if (ch == "<") { |
|||
state.tokenize = doctype(depth + 1); |
|||
return state.tokenize(stream, state); |
|||
} else if (ch == ">") { |
|||
if (depth == 1) { |
|||
state.tokenize = inText; |
|||
break; |
|||
} else { |
|||
state.tokenize = doctype(depth - 1); |
|||
return state.tokenize(stream, state); |
|||
} |
|||
} |
|||
} |
|||
return "meta"; |
|||
}; |
|||
} |
|||
|
|||
function Context(state, tagName, startOfLine) { |
|||
this.prev = state.context; |
|||
this.tagName = tagName; |
|||
this.indent = state.indented; |
|||
this.startOfLine = startOfLine; |
|||
if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent)) |
|||
this.noIndent = true; |
|||
} |
|||
function popContext(state) { |
|||
if (state.context) state.context = state.context.prev; |
|||
} |
|||
function maybePopContext(state, nextTagName) { |
|||
var parentTagName; |
|||
while (true) { |
|||
if (!state.context) { |
|||
return; |
|||
} |
|||
parentTagName = state.context.tagName; |
|||
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || |
|||
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { |
|||
return; |
|||
} |
|||
popContext(state); |
|||
} |
|||
} |
|||
|
|||
function baseState(type, stream, state) { |
|||
if (type == "openTag") { |
|||
state.tagStart = stream.column(); |
|||
return tagNameState; |
|||
} else if (type == "closeTag") { |
|||
return closeTagNameState; |
|||
} else { |
|||
return baseState; |
|||
} |
|||
} |
|||
function tagNameState(type, stream, state) { |
|||
if (type == "word") { |
|||
state.tagName = stream.current(); |
|||
setStyle = "tag"; |
|||
return attrState; |
|||
} else { |
|||
setStyle = "error"; |
|||
return tagNameState; |
|||
} |
|||
} |
|||
function closeTagNameState(type, stream, state) { |
|||
if (type == "word") { |
|||
var tagName = stream.current(); |
|||
if (state.context && state.context.tagName != tagName && |
|||
Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName)) |
|||
popContext(state); |
|||
if (state.context && state.context.tagName == tagName) { |
|||
setStyle = "tag"; |
|||
return closeState; |
|||
} else { |
|||
setStyle = "tag error"; |
|||
return closeStateErr; |
|||
} |
|||
} else { |
|||
setStyle = "error"; |
|||
return closeStateErr; |
|||
} |
|||
} |
|||
|
|||
function closeState(type, _stream, state) { |
|||
if (type != "endTag") { |
|||
setStyle = "error"; |
|||
return closeState; |
|||
} |
|||
popContext(state); |
|||
return baseState; |
|||
} |
|||
function closeStateErr(type, stream, state) { |
|||
setStyle = "error"; |
|||
return closeState(type, stream, state); |
|||
} |
|||
|
|||
function attrState(type, _stream, state) { |
|||
if (type == "word") { |
|||
setStyle = "attribute"; |
|||
return attrEqState; |
|||
} else if (type == "endTag" || type == "selfcloseTag") { |
|||
var tagName = state.tagName, tagStart = state.tagStart; |
|||
state.tagName = state.tagStart = null; |
|||
if (type == "selfcloseTag" || |
|||
Kludges.autoSelfClosers.hasOwnProperty(tagName)) { |
|||
maybePopContext(state, tagName); |
|||
} else { |
|||
maybePopContext(state, tagName); |
|||
state.context = new Context(state, tagName, tagStart == state.indented); |
|||
} |
|||
return baseState; |
|||
} |
|||
setStyle = "error"; |
|||
return attrState; |
|||
} |
|||
function attrEqState(type, stream, state) { |
|||
if (type == "equals") return attrValueState; |
|||
if (!Kludges.allowMissing) setStyle = "error"; |
|||
return attrState(type, stream, state); |
|||
} |
|||
function attrValueState(type, stream, state) { |
|||
if (type == "string") return attrContinuedState; |
|||
if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;} |
|||
setStyle = "error"; |
|||
return attrState(type, stream, state); |
|||
} |
|||
function attrContinuedState(type, stream, state) { |
|||
if (type == "string") return attrContinuedState; |
|||
return attrState(type, stream, state); |
|||
} |
|||
|
|||
return { |
|||
startState: function() { |
|||
return {tokenize: inText, |
|||
state: baseState, |
|||
indented: 0, |
|||
tagName: null, tagStart: null, |
|||
context: null}; |
|||
}, |
|||
|
|||
token: function(stream, state) { |
|||
if (!state.tagName && stream.sol()) |
|||
state.indented = stream.indentation(); |
|||
|
|||
if (stream.eatSpace()) return null; |
|||
type = null; |
|||
var style = state.tokenize(stream, state); |
|||
if ((style || type) && style != "comment") { |
|||
setStyle = null; |
|||
state.state = state.state(type || style, stream, state); |
|||
if (setStyle) |
|||
style = setStyle == "error" ? style + " error" : setStyle; |
|||
} |
|||
return style; |
|||
}, |
|||
|
|||
indent: function(state, textAfter, fullLine) { |
|||
var context = state.context; |
|||
// Indent multi-line strings (e.g. css).
|
|||
if (state.tokenize.isInAttribute) { |
|||
if (state.tagStart == state.indented) |
|||
return state.stringStartCol + 1; |
|||
else |
|||
return state.indented + indentUnit; |
|||
} |
|||
if (context && context.noIndent) return CodeMirror.Pass; |
|||
if (state.tokenize != inTag && state.tokenize != inText) |
|||
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; |
|||
// Indent the starts of attribute names.
|
|||
if (state.tagName) { |
|||
if (multilineTagIndentPastTag) |
|||
return state.tagStart + state.tagName.length + 2; |
|||
else |
|||
return state.tagStart + indentUnit * multilineTagIndentFactor; |
|||
} |
|||
if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0; |
|||
var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter); |
|||
if (tagAfter && tagAfter[1]) { // Closing tag spotted
|
|||
while (context) { |
|||
if (context.tagName == tagAfter[2]) { |
|||
context = context.prev; |
|||
break; |
|||
} else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) { |
|||
context = context.prev; |
|||
} else { |
|||
break; |
|||
} |
|||
} |
|||
} else if (tagAfter) { // Opening tag spotted
|
|||
while (context) { |
|||
var grabbers = Kludges.contextGrabbers[context.tagName]; |
|||
if (grabbers && grabbers.hasOwnProperty(tagAfter[2])) |
|||
context = context.prev; |
|||
else |
|||
break; |
|||
} |
|||
} |
|||
while (context && !context.startOfLine) |
|||
context = context.prev; |
|||
if (context) return context.indent + indentUnit; |
|||
else return 0; |
|||
}, |
|||
|
|||
electricInput: /<\/[\s\w:]+>$/, |
|||
blockCommentStart: "<!--", |
|||
blockCommentEnd: "-->", |
|||
|
|||
configuration: parserConfig.htmlMode ? "html" : "xml", |
|||
helperType: parserConfig.htmlMode ? "html" : "xml" |
|||
}; |
|||
}); |
|||
|
|||
CodeMirror.defineMIME("text/xml", "xml"); |
|||
CodeMirror.defineMIME("application/xml", "xml"); |
|||
if (!CodeMirror.mimeModes.hasOwnProperty("text/html")) |
|||
CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); |
|||
|
|||
}); |
@ -0,0 +1,16 @@ |
|||
<!doctype html> |
|||
<meta charset="utf-8"/> |
|||
<link rel="stylesheet" href="cm/codemirror.css"> |
|||
<link rel="stylesheet" href="cm/solarized.css"> |
|||
<link rel="stylesheet" href="cm/fullscreen.css"> |
|||
<script src="cm/codemirror.js"></script> |
|||
<script src="cm/javascript.js"></script> |
|||
<script src="cm/css.js"></script> |
|||
<script src="cm/xml.js"></script> |
|||
<script src="cm/htmlmixed.js"></script> |
|||
<script src="cm/solidity.js"></script> |
|||
<script src="cm/fullscreen.js"></script> |
|||
<script src="cm/active-line.js"></script> |
|||
<script src="cm/matchbrackets.js"></script> |
|||
<body oncontextmenu="return false;"></body> |
|||
<script src="codeeditor.js"></script> |
@ -0,0 +1,42 @@ |
|||
|
|||
var editor = CodeMirror(document.body, { |
|||
lineNumbers: true, |
|||
//styleActiveLine: true,
|
|||
matchBrackets: true, |
|||
autofocus: true, |
|||
indentWithTabs: true, |
|||
}); |
|||
|
|||
editor.setOption("theme", "solarized dark"); |
|||
editor.setOption("fullScreen", true); |
|||
|
|||
editor.changeRegistered = false; |
|||
|
|||
editor.on("change", function(eMirror, object) { |
|||
editor.changeRegistered = true; |
|||
|
|||
}); |
|||
|
|||
getTextChanged = function() { |
|||
return editor.changeRegistered; |
|||
}; |
|||
|
|||
|
|||
getText = function() { |
|||
editor.changeRegistered = false; |
|||
return editor.getValue(); |
|||
}; |
|||
|
|||
|
|||
setTextBase64 = function(text) { |
|||
editor.setValue(window.atob(text)); |
|||
editor.focus(); |
|||
}; |
|||
|
|||
setText = function(text) { |
|||
editor.setValue(text); |
|||
}; |
|||
|
|||
setMode = function(mode) { |
|||
this.editor.setOption("mode", mode); |
|||
}; |
Loading…
Reference in new issue