Last active
March 6, 2024 09:49
-
-
Save SnowWarri0r/8ae79581b2defdddd88a697b97afb21d to your computer and use it in GitHub Desktop.
ACE Editor toml worker that can be used directly, you can see https://www.onesnowwarrior.cn/archives/136.html to know how to use
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"no use strict"; | |
!(function (window) { | |
if (typeof window.window != "undefined" && window.document) | |
return; | |
if (window.require && window.define) | |
return; | |
if (!window.console) { | |
window.console = function () { | |
var msgs = Array.prototype.slice.call(arguments, 0); | |
postMessage({ type: "log", data: msgs }); | |
}; | |
window.console.error = | |
window.console.warn = | |
window.console.log = | |
window.console.trace = window.console; | |
} | |
window.window = window; | |
window.ace = window; | |
window.onerror = function (message, file, line, col, err) { | |
postMessage({ | |
type: "error", data: { | |
message: message, | |
data: err && err.data, | |
file: file, | |
line: line, | |
col: col, | |
stack: err && err.stack | |
} | |
}); | |
}; | |
window.normalizeModule = function (parentId, moduleName) { | |
// normalize plugin requires | |
if (moduleName.indexOf("!") !== -1) { | |
var chunks = moduleName.split("!"); | |
return window.normalizeModule(parentId, chunks[0]) + "!" + window.normalizeModule(parentId, chunks[1]); | |
} | |
// normalize relative requires | |
if (moduleName.charAt(0) == ".") { | |
var base = parentId.split("/").slice(0, -1).join("/"); | |
moduleName = (base ? base + "/" : "") + moduleName; | |
while (moduleName.indexOf(".") !== -1 && previous != moduleName) { | |
var previous = moduleName; | |
moduleName = moduleName.replace(/^\.\//, "").replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); | |
} | |
} | |
return moduleName; | |
}; | |
window.require = function require(parentId, id) { | |
if (!id) { | |
id = parentId; | |
parentId = null; | |
} | |
if (!id.charAt) | |
throw new Error("worker.js require() accepts only (parentId, id) as arguments"); | |
id = window.normalizeModule(parentId, id); | |
var module = window.require.modules[id]; | |
if (module) { | |
if (!module.initialized) { | |
module.initialized = true; | |
module.exports = module.factory().exports; | |
} | |
return module.exports; | |
} | |
if (!window.require.tlns) | |
return console.log("unable to load " + id); | |
var path = resolveModuleId(id, window.require.tlns); | |
if (path.slice(-3) != ".js") path += ".js"; | |
window.require.id = id; | |
window.require.modules[id] = {}; // prevent infinite loop on broken modules | |
importScripts(path); | |
return window.require(parentId, id); | |
}; | |
function resolveModuleId(id, paths) { | |
var testPath = id, tail = ""; | |
while (testPath) { | |
var alias = paths[testPath]; | |
if (typeof alias == "string") { | |
return alias + tail; | |
} else if (alias) { | |
return alias.location.replace(/\/*$/, "/") + (tail || alias.main || alias.name); | |
} else if (alias === false) { | |
return ""; | |
} | |
var i = testPath.lastIndexOf("/"); | |
if (i === -1) break; | |
tail = testPath.substr(i) + tail; | |
testPath = testPath.slice(0, i); | |
} | |
return id; | |
} | |
window.require.modules = {}; | |
window.require.tlns = {}; | |
window.define = function (id, deps, factory) { | |
if (arguments.length == 2) { | |
factory = deps; | |
if (typeof id != "string") { | |
deps = id; | |
id = window.require.id; | |
} | |
} else if (arguments.length == 1) { | |
factory = id; | |
deps = []; | |
id = window.require.id; | |
} | |
if (typeof factory != "function") { | |
window.require.modules[id] = { | |
exports: factory, | |
initialized: true | |
}; | |
return; | |
} | |
if (!deps.length) | |
// If there is no dependencies, we inject "require", "exports" and | |
// "module" as dependencies, to provide CommonJS compatibility. | |
deps = ["require", "exports", "module"]; | |
var req = function (childId) { | |
return window.require(id, childId); | |
}; | |
window.require.modules[id] = { | |
exports: {}, | |
factory: function () { | |
var module = this; | |
var returnExports = factory.apply(this, deps.slice(0, factory.length).map(function (dep) { | |
switch (dep) { | |
// Because "require", "exports" and "module" aren't actual | |
// dependencies, we must handle them seperately. | |
case "require": return req; | |
case "exports": return module.exports; | |
case "module": return module; | |
// But for all other dependencies, we can just go ahead and | |
// require them. | |
default: return req(dep); | |
} | |
})); | |
if (returnExports) | |
module.exports = returnExports; | |
return module; | |
} | |
}; | |
}; | |
window.define.amd = {}; | |
window.require.tlns = {}; | |
window.initBaseUrls = function initBaseUrls(topLevelNamespaces) { | |
for (var i in topLevelNamespaces) | |
this.require.tlns[i] = topLevelNamespaces[i]; | |
}; | |
window.initSender = function initSender() { | |
var EventEmitter = window.require("ace/lib/event_emitter").EventEmitter; | |
var oop = window.require("ace/lib/oop"); | |
var Sender = function () { }; | |
(function () { | |
oop.implement(this, EventEmitter); | |
this.callback = function (data, callbackId) { | |
postMessage({ | |
type: "call", | |
id: callbackId, | |
data: data | |
}); | |
}; | |
this.emit = function (name, data) { | |
postMessage({ | |
type: "event", | |
name: name, | |
data: data | |
}); | |
}; | |
}).call(Sender.prototype); | |
return new Sender(); | |
}; | |
var main = window.main = null; | |
var sender = window.sender = null; | |
window.onmessage = function (e) { | |
var msg = e.data; | |
if (msg.event && sender) { | |
sender._signal(msg.event, msg.data); | |
} | |
else if (msg.command) { | |
if (main[msg.command]) | |
main[msg.command].apply(main, msg.args); | |
else if (window[msg.command]) | |
window[msg.command].apply(window, msg.args); | |
else | |
throw new Error("Unknown command:" + msg.command); | |
} | |
else if (msg.init) { | |
window.initBaseUrls(msg.tlns); | |
sender = window.sender = window.initSender(); | |
var clazz = this.require(msg.module)[msg.classname]; | |
main = window.main = new clazz(sender); | |
} | |
}; | |
})(this); | |
ace.define("ace/lib/oop", [], function (require, exports, module) { | |
"use strict"; | |
exports.inherits = function (ctor, superCtor) { | |
ctor.super_ = superCtor; | |
ctor.prototype = Object.create(superCtor.prototype, { | |
constructor: { | |
value: ctor, | |
enumerable: false, | |
writable: true, | |
configurable: true | |
} | |
}); | |
}; | |
exports.mixin = function (obj, mixin) { | |
for (var key in mixin) { | |
obj[key] = mixin[key]; | |
} | |
return obj; | |
}; | |
exports.implement = function (proto, mixin) { | |
exports.mixin(proto, mixin); | |
}; | |
}); | |
ace.define("ace/apply_delta", [], function (require, exports, module) { | |
"use strict"; | |
function throwDeltaError(delta, errorText) { | |
console.log("Invalid Delta:", delta); | |
throw "Invalid Delta: " + errorText; | |
} | |
function positionInDocument(docLines, position) { | |
return position.row >= 0 && position.row < docLines.length && | |
position.column >= 0 && position.column <= docLines[position.row].length; | |
} | |
exports.applyDelta = function (docLines, delta, doNotValidate) { | |
var row = delta.start.row; | |
var startColumn = delta.start.column; | |
var line = docLines[row] || ""; | |
switch (delta.action) { | |
case "insert": | |
var lines = delta.lines; | |
if (lines.length === 1) { | |
docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); | |
} | |
else { | |
var args = [row, 1].concat(delta.lines); | |
docLines.splice.apply(docLines, args); | |
docLines[row] = line.substring(0, startColumn) + docLines[row]; | |
docLines[row + delta.lines.length - 1] += line.substring(startColumn); | |
} | |
break; | |
case "remove": | |
var endColumn = delta.end.column; | |
var endRow = delta.end.row; | |
if (row === endRow) { | |
docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); | |
} | |
else { | |
docLines.splice(row, endRow - row + 1, line.substring(0, startColumn) + docLines[endRow].substring(endColumn)); | |
} | |
break; | |
} | |
}; | |
}); | |
ace.define("ace/lib/event_emitter", [], function (require, exports, module) { | |
"use strict"; | |
var EventEmitter = {}; | |
class stopPropagation { | |
constructor() { this.propagationStopped = true; } | |
} | |
class preventDefault { | |
constructor() { this.defaultPrevented = true; } | |
} | |
EventEmitter._emit = | |
EventEmitter._dispatchEvent = function (eventName, e) { | |
this._eventRegistry || (this._eventRegistry = {}); | |
this._defaultHandlers || (this._defaultHandlers = {}); | |
var listeners = this._eventRegistry[eventName] || []; | |
var defaultHandler = this._defaultHandlers[eventName]; | |
if (!listeners.length && !defaultHandler) | |
return; | |
if (typeof e != "object" || !e) | |
e = {}; | |
if (!e.type) | |
e.type = eventName; | |
if (!e.stopPropagation) | |
e.stopPropagation = stopPropagation; | |
if (!e.preventDefault) | |
e.preventDefault = preventDefault; | |
listeners = listeners.slice(); | |
for (var i = 0; i < listeners.length; i++) { | |
listeners[i](e, this); | |
if (e.propagationStopped) | |
break; | |
} | |
if (defaultHandler && !e.defaultPrevented) | |
return defaultHandler(e, this); | |
}; | |
EventEmitter._signal = function (eventName, e) { | |
var listeners = (this._eventRegistry || {})[eventName]; | |
if (!listeners) | |
return; | |
listeners = listeners.slice(); | |
for (var i = 0; i < listeners.length; i++) | |
listeners[i](e, this); | |
}; | |
EventEmitter.once = function (eventName, callback) { | |
var _self = this; | |
this.on(eventName, function newCallback() { | |
_self.off(eventName, newCallback); | |
callback.apply(null, arguments); | |
}); | |
if (!callback) { | |
return new Promise(function (resolve) { | |
callback = resolve; | |
}); | |
} | |
}; | |
EventEmitter.setDefaultHandler = function (eventName, callback) { | |
var handlers = this._defaultHandlers; | |
if (!handlers) | |
handlers = this._defaultHandlers = { _disabled_: {} }; | |
if (handlers[eventName]) { | |
var old = handlers[eventName]; | |
var disabled = handlers._disabled_[eventName]; | |
if (!disabled) | |
handlers._disabled_[eventName] = disabled = []; | |
disabled.push(old); | |
var i = disabled.indexOf(callback); | |
if (i != -1) | |
disabled.splice(i, 1); | |
} | |
handlers[eventName] = callback; | |
}; | |
EventEmitter.removeDefaultHandler = function (eventName, callback) { | |
var handlers = this._defaultHandlers; | |
if (!handlers) | |
return; | |
var disabled = handlers._disabled_[eventName]; | |
if (handlers[eventName] == callback) { | |
if (disabled) | |
this.setDefaultHandler(eventName, disabled.pop()); | |
} | |
else if (disabled) { | |
var i = disabled.indexOf(callback); | |
if (i != -1) | |
disabled.splice(i, 1); | |
} | |
}; | |
EventEmitter.on = | |
EventEmitter.addEventListener = function (eventName, callback, capturing) { | |
this._eventRegistry = this._eventRegistry || {}; | |
var listeners = this._eventRegistry[eventName]; | |
if (!listeners) | |
listeners = this._eventRegistry[eventName] = []; | |
if (listeners.indexOf(callback) == -1) | |
listeners[capturing ? "unshift" : "push"](callback); | |
return callback; | |
}; | |
EventEmitter.off = | |
EventEmitter.removeListener = | |
EventEmitter.removeEventListener = function (eventName, callback) { | |
this._eventRegistry = this._eventRegistry || {}; | |
var listeners = this._eventRegistry[eventName]; | |
if (!listeners) | |
return; | |
var index = listeners.indexOf(callback); | |
if (index !== -1) | |
listeners.splice(index, 1); | |
}; | |
EventEmitter.removeAllListeners = function (eventName) { | |
if (!eventName) | |
this._eventRegistry = this._defaultHandlers = undefined; | |
if (this._eventRegistry) | |
this._eventRegistry[eventName] = undefined; | |
if (this._defaultHandlers) | |
this._defaultHandlers[eventName] = undefined; | |
}; | |
exports.EventEmitter = EventEmitter; | |
}); | |
ace.define("ace/range", [], function (require, exports, module) { | |
"use strict"; | |
var Range = /** @class */ (function () { | |
class Range { | |
constructor(startRow, startColumn, endRow, endColumn) { | |
this.start = { | |
row: startRow, | |
column: startColumn | |
}; | |
this.end = { | |
row: endRow, | |
column: endColumn | |
}; | |
} | |
isEqual(range) { | |
return this.start.row === range.start.row && | |
this.end.row === range.end.row && | |
this.start.column === range.start.column && | |
this.end.column === range.end.column; | |
} | |
toString() { | |
return ("Range: [" + this.start.row + "/" + this.start.column + | |
"] -> [" + this.end.row + "/" + this.end.column + "]"); | |
} | |
contains(row, column) { | |
return this.compare(row, column) == 0; | |
} | |
compareRange(range) { | |
var cmp, end = range.end, start = range.start; | |
cmp = this.compare(end.row, end.column); | |
if (cmp == 1) { | |
cmp = this.compare(start.row, start.column); | |
if (cmp == 1) { | |
return 2; | |
} | |
else if (cmp == 0) { | |
return 1; | |
} | |
else { | |
return 0; | |
} | |
} | |
else if (cmp == -1) { | |
return -2; | |
} | |
else { | |
cmp = this.compare(start.row, start.column); | |
if (cmp == -1) { | |
return -1; | |
} | |
else if (cmp == 1) { | |
return 42; | |
} | |
else { | |
return 0; | |
} | |
} | |
} | |
comparePoint(p) { | |
return this.compare(p.row, p.column); | |
} | |
containsRange(range) { | |
return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; | |
} | |
intersects(range) { | |
var cmp = this.compareRange(range); | |
return (cmp == -1 || cmp == 0 || cmp == 1); | |
} | |
isEnd(row, column) { | |
return this.end.row == row && this.end.column == column; | |
} | |
isStart(row, column) { | |
return this.start.row == row && this.start.column == column; | |
} | |
setStart(row, column) { | |
if (typeof row == "object") { | |
this.start.column = row.column; | |
this.start.row = row.row; | |
} | |
else { | |
this.start.row = row; | |
this.start.column = column; | |
} | |
} | |
setEnd(row, column) { | |
if (typeof row == "object") { | |
this.end.column = row.column; | |
this.end.row = row.row; | |
} | |
else { | |
this.end.row = row; | |
this.end.column = column; | |
} | |
} | |
inside(row, column) { | |
if (this.compare(row, column) == 0) { | |
if (this.isEnd(row, column) || this.isStart(row, column)) { | |
return false; | |
} | |
else { | |
return true; | |
} | |
} | |
return false; | |
} | |
insideStart(row, column) { | |
if (this.compare(row, column) == 0) { | |
if (this.isEnd(row, column)) { | |
return false; | |
} | |
else { | |
return true; | |
} | |
} | |
return false; | |
} | |
insideEnd(row, column) { | |
if (this.compare(row, column) == 0) { | |
if (this.isStart(row, column)) { | |
return false; | |
} | |
else { | |
return true; | |
} | |
} | |
return false; | |
} | |
compare(row, column) { | |
if (!this.isMultiLine()) { | |
if (row === this.start.row) { | |
return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); | |
} | |
} | |
if (row < this.start.row) | |
return -1; | |
if (row > this.end.row) | |
return 1; | |
if (this.start.row === row) | |
return column >= this.start.column ? 0 : -1; | |
if (this.end.row === row) | |
return column <= this.end.column ? 0 : 1; | |
return 0; | |
} | |
compareStart(row, column) { | |
if (this.start.row == row && this.start.column == column) { | |
return -1; | |
} | |
else { | |
return this.compare(row, column); | |
} | |
} | |
compareEnd(row, column) { | |
if (this.end.row == row && this.end.column == column) { | |
return 1; | |
} | |
else { | |
return this.compare(row, column); | |
} | |
} | |
compareInside(row, column) { | |
if (this.end.row == row && this.end.column == column) { | |
return 1; | |
} | |
else if (this.start.row == row && this.start.column == column) { | |
return -1; | |
} | |
else { | |
return this.compare(row, column); | |
} | |
} | |
clipRows(firstRow, lastRow) { | |
if (this.end.row > lastRow) | |
var end = { row: lastRow + 1, column: 0 }; | |
else if (this.end.row < firstRow) | |
var end = { row: firstRow, column: 0 }; | |
if (this.start.row > lastRow) | |
var start = { row: lastRow + 1, column: 0 }; | |
else if (this.start.row < firstRow) | |
var start = { row: firstRow, column: 0 }; | |
return Range.fromPoints(start || this.start, end || this.end); | |
} | |
extend(row, column) { | |
var cmp = this.compare(row, column); | |
if (cmp == 0) | |
return this; | |
else if (cmp == -1) | |
var start = { row: row, column: column }; | |
else | |
var end = { row: row, column: column }; | |
return Range.fromPoints(start || this.start, end || this.end); | |
} | |
isEmpty() { | |
return (this.start.row === this.end.row && this.start.column === this.end.column); | |
} | |
isMultiLine() { | |
return (this.start.row !== this.end.row); | |
} | |
clone() { | |
return Range.fromPoints(this.start, this.end); | |
} | |
collapseRows() { | |
if (this.end.column == 0) | |
return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row - 1), 0); | |
else | |
return new Range(this.start.row, 0, this.end.row, 0); | |
} | |
toScreenRange(session) { | |
var screenPosStart = session.documentToScreenPosition(this.start); | |
var screenPosEnd = session.documentToScreenPosition(this.end); | |
return new Range(screenPosStart.row, screenPosStart.column, screenPosEnd.row, screenPosEnd.column); | |
} | |
moveBy(row, column) { | |
this.start.row += row; | |
this.start.column += column; | |
this.end.row += row; | |
this.end.column += column; | |
} | |
} | |
return Range; | |
}()); | |
Range.fromPoints = function (start, end) { | |
return new Range(start.row, start.column, end.row, end.column); | |
}; | |
Range.comparePoints = function (p1, p2) { | |
return p1.row - p2.row || p1.column - p2.column; | |
}; | |
exports.Range = Range; | |
}); | |
ace.define("ace/anchor", [], function (require, exports, module) { | |
"use strict"; | |
var oop = require("./lib/oop"); | |
var EventEmitter = require("./lib/event_emitter").EventEmitter; | |
var Anchor = /** @class */ (function () { | |
class Anchor { | |
constructor(doc, row, column) { | |
this.$onChange = this.onChange.bind(this); | |
this.attach(doc); | |
if (typeof row != "number") | |
this.setPosition(row.row, row.column); | |
else | |
this.setPosition(row, column); | |
} | |
getPosition() { | |
return this.$clipPositionToDocument(this.row, this.column); | |
} | |
getDocument() { | |
return this.document; | |
} | |
onChange(delta) { | |
if (delta.start.row == delta.end.row && delta.start.row != this.row) | |
return; | |
if (delta.start.row > this.row) | |
return; | |
var point = $getTransformedPoint(delta, { row: this.row, column: this.column }, this.$insertRight); | |
this.setPosition(point.row, point.column, true); | |
} | |
setPosition(row, column, noClip) { | |
var pos; | |
if (noClip) { | |
pos = { | |
row: row, | |
column: column | |
}; | |
} | |
else { | |
pos = this.$clipPositionToDocument(row, column); | |
} | |
if (this.row == pos.row && this.column == pos.column) | |
return; | |
var old = { | |
row: this.row, | |
column: this.column | |
}; | |
this.row = pos.row; | |
this.column = pos.column; | |
this._signal("change", { | |
old: old, | |
value: pos | |
}); | |
} | |
detach() { | |
this.document.off("change", this.$onChange); | |
} | |
attach(doc) { | |
this.document = doc || this.document; | |
this.document.on("change", this.$onChange); | |
} | |
$clipPositionToDocument(row, column) { | |
var pos = {}; | |
if (row >= this.document.getLength()) { | |
pos.row = Math.max(0, this.document.getLength() - 1); | |
pos.column = this.document.getLine(pos.row).length; | |
} | |
else if (row < 0) { | |
pos.row = 0; | |
pos.column = 0; | |
} | |
else { | |
pos.row = row; | |
pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); | |
} | |
if (column < 0) | |
pos.column = 0; | |
return pos; | |
} | |
} | |
return Anchor; | |
}()); | |
Anchor.prototype.$insertRight = false; | |
oop.implement(Anchor.prototype, EventEmitter); | |
function $pointsInOrder(point1, point2, equalPointsInOrder) { | |
var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column; | |
return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter); | |
} | |
function $getTransformedPoint(delta, point, moveIfEqual) { | |
var deltaIsInsert = delta.action == "insert"; | |
var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row); | |
var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column); | |
var deltaStart = delta.start; | |
var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range. | |
if ($pointsInOrder(point, deltaStart, moveIfEqual)) { | |
return { | |
row: point.row, | |
column: point.column | |
}; | |
} | |
if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) { | |
return { | |
row: point.row + deltaRowShift, | |
column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0) | |
}; | |
} | |
return { | |
row: deltaStart.row, | |
column: deltaStart.column | |
}; | |
} | |
exports.Anchor = Anchor; | |
}); | |
ace.define("ace/document", [], function (require, exports, module) { | |
"use strict"; | |
var oop = require("./lib/oop"); | |
var applyDelta = require("./apply_delta").applyDelta; | |
var EventEmitter = require("./lib/event_emitter").EventEmitter; | |
var Range = require("./range").Range; | |
var Anchor = require("./anchor").Anchor; | |
var Document = /** @class */ (function () { | |
function Document(textOrLines) { | |
this.$lines = [""]; | |
if (textOrLines.length === 0) { | |
this.$lines = [""]; | |
} | |
else if (Array.isArray(textOrLines)) { | |
this.insertMergedLines({ row: 0, column: 0 }, textOrLines); | |
} | |
else { | |
this.insert({ row: 0, column: 0 }, textOrLines); | |
} | |
} | |
Document.prototype.setValue = function (text) { | |
var len = this.getLength() - 1; | |
this.remove(new Range(0, 0, len, this.getLine(len).length)); | |
this.insert({ row: 0, column: 0 }, text || ""); | |
}; | |
Document.prototype.getValue = function () { | |
return this.getAllLines().join(this.getNewLineCharacter()); | |
}; | |
Document.prototype.createAnchor = function (row, column) { | |
return new Anchor(this, row, column); | |
}; | |
Document.prototype.$detectNewLine = function (text) { | |
var match = text.match(/^.*?(\r\n|\r|\n)/m); | |
this.$autoNewLine = match ? match[1] : "\n"; | |
this._signal("changeNewLineMode"); | |
}; | |
Document.prototype.getNewLineCharacter = function () { | |
switch (this.$newLineMode) { | |
case "windows": | |
return "\r\n"; | |
case "unix": | |
return "\n"; | |
default: | |
return this.$autoNewLine || "\n"; | |
} | |
}; | |
Document.prototype.setNewLineMode = function (newLineMode) { | |
if (this.$newLineMode === newLineMode) | |
return; | |
this.$newLineMode = newLineMode; | |
this._signal("changeNewLineMode"); | |
}; | |
Document.prototype.getNewLineMode = function () { | |
return this.$newLineMode; | |
}; | |
Document.prototype.isNewLine = function (text) { | |
return (text == "\r\n" || text == "\r" || text == "\n"); | |
}; | |
Document.prototype.getLine = function (row) { | |
return this.$lines[row] || ""; | |
}; | |
Document.prototype.getLines = function (firstRow, lastRow) { | |
return this.$lines.slice(firstRow, lastRow + 1); | |
}; | |
Document.prototype.getAllLines = function () { | |
return this.getLines(0, this.getLength()); | |
}; | |
Document.prototype.getLength = function () { | |
return this.$lines.length; | |
}; | |
Document.prototype.getTextRange = function (range) { | |
return this.getLinesForRange(range).join(this.getNewLineCharacter()); | |
}; | |
Document.prototype.getLinesForRange = function (range) { | |
var lines; | |
if (range.start.row === range.end.row) { | |
lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)]; | |
} | |
else { | |
lines = this.getLines(range.start.row, range.end.row); | |
lines[0] = (lines[0] || "").substring(range.start.column); | |
var l = lines.length - 1; | |
if (range.end.row - range.start.row == l) | |
lines[l] = lines[l].substring(0, range.end.column); | |
} | |
return lines; | |
}; | |
Document.prototype.insertLines = function (row, lines) { | |
console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."); | |
return this.insertFullLines(row, lines); | |
}; | |
Document.prototype.removeLines = function (firstRow, lastRow) { | |
console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."); | |
return this.removeFullLines(firstRow, lastRow); | |
}; | |
Document.prototype.insertNewLine = function (position) { | |
console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, ['', '']) instead."); | |
return this.insertMergedLines(position, ["", ""]); | |
}; | |
Document.prototype.insert = function (position, text) { | |
if (this.getLength() <= 1) | |
this.$detectNewLine(text); | |
return this.insertMergedLines(position, this.$split(text)); | |
}; | |
Document.prototype.insertInLine = function (position, text) { | |
var start = this.clippedPos(position.row, position.column); | |
var end = this.pos(position.row, position.column + text.length); | |
this.applyDelta({ | |
start: start, | |
end: end, | |
action: "insert", | |
lines: [text] | |
}, true); | |
return this.clonePos(end); | |
}; | |
Document.prototype.clippedPos = function (row, column) { | |
var length = this.getLength(); | |
if (row === undefined) { | |
row = length; | |
} | |
else if (row < 0) { | |
row = 0; | |
} | |
else if (row >= length) { | |
row = length - 1; | |
column = undefined; | |
} | |
var line = this.getLine(row); | |
if (column == undefined) | |
column = line.length; | |
column = Math.min(Math.max(column, 0), line.length); | |
return { row: row, column: column }; | |
}; | |
Document.prototype.clonePos = function (pos) { | |
return { row: pos.row, column: pos.column }; | |
}; | |
Document.prototype.pos = function (row, column) { | |
return { row: row, column: column }; | |
}; | |
Document.prototype.$clipPosition = function (position) { | |
var length = this.getLength(); | |
if (position.row >= length) { | |
position.row = Math.max(0, length - 1); | |
position.column = this.getLine(length - 1).length; | |
} | |
else { | |
position.row = Math.max(0, position.row); | |
position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length); | |
} | |
return position; | |
}; | |
Document.prototype.insertFullLines = function (row, lines) { | |
row = Math.min(Math.max(row, 0), this.getLength()); | |
var column = 0; | |
if (row < this.getLength()) { | |
lines = lines.concat([""]); | |
column = 0; | |
} | |
else { | |
lines = [""].concat(lines); | |
row--; | |
column = this.$lines[row].length; | |
} | |
this.insertMergedLines({ row: row, column: column }, lines); | |
}; | |
Document.prototype.insertMergedLines = function (position, lines) { | |
var start = this.clippedPos(position.row, position.column); | |
var end = { | |
row: start.row + lines.length - 1, | |
column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length | |
}; | |
this.applyDelta({ | |
start: start, | |
end: end, | |
action: "insert", | |
lines: lines | |
}); | |
return this.clonePos(end); | |
}; | |
Document.prototype.remove = function (range) { | |
var start = this.clippedPos(range.start.row, range.start.column); | |
var end = this.clippedPos(range.end.row, range.end.column); | |
this.applyDelta({ | |
start: start, | |
end: end, | |
action: "remove", | |
lines: this.getLinesForRange({ start: start, end: end }) | |
}); | |
return this.clonePos(start); | |
}; | |
Document.prototype.removeInLine = function (row, startColumn, endColumn) { | |
var start = this.clippedPos(row, startColumn); | |
var end = this.clippedPos(row, endColumn); | |
this.applyDelta({ | |
start: start, | |
end: end, | |
action: "remove", | |
lines: this.getLinesForRange({ start: start, end: end }) | |
}, true); | |
return this.clonePos(start); | |
}; | |
Document.prototype.removeFullLines = function (firstRow, lastRow) { | |
firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1); | |
lastRow = Math.min(Math.max(0, lastRow), this.getLength() - 1); | |
var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0; | |
var deleteLastNewLine = lastRow < this.getLength() - 1; | |
var startRow = (deleteFirstNewLine ? firstRow - 1 : firstRow); | |
var startCol = (deleteFirstNewLine ? this.getLine(startRow).length : 0); | |
var endRow = (deleteLastNewLine ? lastRow + 1 : lastRow); | |
var endCol = (deleteLastNewLine ? 0 : this.getLine(endRow).length); | |
var range = new Range(startRow, startCol, endRow, endCol); | |
var deletedLines = this.$lines.slice(firstRow, lastRow + 1); | |
this.applyDelta({ | |
start: range.start, | |
end: range.end, | |
action: "remove", | |
lines: this.getLinesForRange(range) | |
}); | |
return deletedLines; | |
}; | |
Document.prototype.removeNewLine = function (row) { | |
if (row < this.getLength() - 1 && row >= 0) { | |
this.applyDelta({ | |
start: this.pos(row, this.getLine(row).length), | |
end: this.pos(row + 1, 0), | |
action: "remove", | |
lines: ["", ""] | |
}); | |
} | |
}; | |
Document.prototype.replace = function (range, text) { | |
if (!(range instanceof Range)) | |
range = Range.fromPoints(range.start, range.end); | |
if (text.length === 0 && range.isEmpty()) | |
return range.start; | |
if (text == this.getTextRange(range)) | |
return range.end; | |
this.remove(range); | |
var end; | |
if (text) { | |
end = this.insert(range.start, text); | |
} | |
else { | |
end = range.start; | |
} | |
return end; | |
}; | |
Document.prototype.applyDeltas = function (deltas) { | |
for (var i = 0; i < deltas.length; i++) { | |
this.applyDelta(deltas[i]); | |
} | |
}; | |
Document.prototype.revertDeltas = function (deltas) { | |
for (var i = deltas.length - 1; i >= 0; i--) { | |
this.revertDelta(deltas[i]); | |
} | |
}; | |
Document.prototype.applyDelta = function (delta, doNotValidate) { | |
var isInsert = delta.action == "insert"; | |
if (isInsert ? delta.lines.length <= 1 && !delta.lines[0] | |
: !Range.comparePoints(delta.start, delta.end)) { | |
return; | |
} | |
if (isInsert && delta.lines.length > 20000) { | |
this.$splitAndapplyLargeDelta(delta, 20000); | |
} | |
else { | |
applyDelta(this.$lines, delta, doNotValidate); | |
this._signal("change", delta); | |
} | |
}; | |
Document.prototype.$safeApplyDelta = function (delta) { | |
var docLength = this.$lines.length; | |
if (delta.action == "remove" && delta.start.row < docLength && delta.end.row < docLength | |
|| delta.action == "insert" && delta.start.row <= docLength) { | |
this.applyDelta(delta); | |
} | |
}; | |
Document.prototype.$splitAndapplyLargeDelta = function (delta, MAX) { | |
var lines = delta.lines; | |
var l = lines.length - MAX + 1; | |
var row = delta.start.row; | |
var column = delta.start.column; | |
for (var from = 0, to = 0; from < l; from = to) { | |
to += MAX - 1; | |
var chunk = lines.slice(from, to); | |
chunk.push(""); | |
this.applyDelta({ | |
start: this.pos(row + from, column), | |
end: this.pos(row + to, column = 0), | |
action: delta.action, | |
lines: chunk | |
}, true); | |
} | |
delta.lines = lines.slice(from); | |
delta.start.row = row + from; | |
delta.start.column = column; | |
this.applyDelta(delta, true); | |
}; | |
Document.prototype.revertDelta = function (delta) { | |
this.$safeApplyDelta({ | |
start: this.clonePos(delta.start), | |
end: this.clonePos(delta.end), | |
action: (delta.action == "insert" ? "remove" : "insert"), | |
lines: delta.lines.slice() | |
}); | |
}; | |
Document.prototype.indexToPosition = function (index, startRow) { | |
var lines = this.$lines || this.getAllLines(); | |
var newlineLength = this.getNewLineCharacter().length; | |
for (var i = startRow || 0, l = lines.length; i < l; i++) { | |
index -= lines[i].length + newlineLength; | |
if (index < 0) | |
return { row: i, column: index + lines[i].length + newlineLength }; | |
} | |
return { row: l - 1, column: index + lines[l - 1].length + newlineLength }; | |
}; | |
Document.prototype.positionToIndex = function (pos, startRow) { | |
var lines = this.$lines || this.getAllLines(); | |
var newlineLength = this.getNewLineCharacter().length; | |
var index = 0; | |
var row = Math.min(pos.row, lines.length); | |
for (var i = startRow || 0; i < row; ++i) | |
index += lines[i].length + newlineLength; | |
return index + pos.column; | |
}; | |
Document.prototype.$split = function (text) { | |
return text.split(/\r\n|\r|\n/); | |
}; | |
return Document; | |
}()); | |
Document.prototype.$autoNewLine = ""; | |
Document.prototype.$newLineMode = "auto"; | |
oop.implement(Document.prototype, EventEmitter); | |
exports.Document = Document; | |
}); | |
ace.define("ace/lib/deep_copy", [], function (require, exports, module) { | |
exports.deepCopy = function deepCopy(obj) { | |
if (typeof obj !== "object" || !obj) | |
return obj; | |
var copy; | |
if (Array.isArray(obj)) { | |
copy = []; | |
for (var key = 0; key < obj.length; key++) { | |
copy[key] = deepCopy(obj[key]); | |
} | |
return copy; | |
} | |
if (Object.prototype.toString.call(obj) !== "[object Object]") | |
return obj; | |
copy = {}; | |
for (var key in obj) | |
copy[key] = deepCopy(obj[key]); | |
return copy; | |
}; | |
}); | |
ace.define("ace/lib/lang", [], function (require, exports, module) { | |
"use strict"; | |
exports.last = function (a) { | |
return a[a.length - 1]; | |
}; | |
exports.stringReverse = function (string) { | |
return string.split("").reverse().join(""); | |
}; | |
exports.stringRepeat = function (string, count) { | |
var result = ''; | |
while (count > 0) { | |
if (count & 1) | |
result += string; | |
if (count >>= 1) | |
string += string; | |
} | |
return result; | |
}; | |
var trimBeginRegexp = /^\s\s*/; | |
var trimEndRegexp = /\s\s*$/; | |
exports.stringTrimLeft = function (string) { | |
return string.replace(trimBeginRegexp, ''); | |
}; | |
exports.stringTrimRight = function (string) { | |
return string.replace(trimEndRegexp, ''); | |
}; | |
exports.copyObject = function (obj) { | |
var copy = {}; | |
for (var key in obj) { | |
copy[key] = obj[key]; | |
} | |
return copy; | |
}; | |
exports.copyArray = function (array) { | |
var copy = []; | |
for (var i = 0, l = array.length; i < l; i++) { | |
if (array[i] && typeof array[i] == "object") | |
copy[i] = this.copyObject(array[i]); | |
else | |
copy[i] = array[i]; | |
} | |
return copy; | |
}; | |
exports.deepCopy = require("./deep_copy").deepCopy; | |
exports.arrayToMap = function (arr) { | |
var map = {}; | |
for (var i = 0; i < arr.length; i++) { | |
map[arr[i]] = 1; | |
} | |
return map; | |
}; | |
exports.createMap = function (props) { | |
var map = Object.create(null); | |
for (var i in props) { | |
map[i] = props[i]; | |
} | |
return map; | |
}; | |
exports.arrayRemove = function (array, value) { | |
for (var i = 0; i <= array.length; i++) { | |
if (value === array[i]) { | |
array.splice(i, 1); | |
} | |
} | |
}; | |
exports.escapeRegExp = function (str) { | |
return str.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); | |
}; | |
exports.escapeHTML = function (str) { | |
return ("" + str).replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<"); | |
}; | |
exports.getMatchOffsets = function (string, regExp) { | |
var matches = []; | |
string.replace(regExp, function (str) { | |
matches.push({ | |
offset: arguments[arguments.length - 2], | |
length: str.length | |
}); | |
}); | |
return matches; | |
}; | |
exports.deferredCall = function (fcn) { | |
var timer = null; | |
var callback = function () { | |
timer = null; | |
fcn(); | |
}; | |
var deferred = function (timeout) { | |
deferred.cancel(); | |
timer = setTimeout(callback, timeout || 0); | |
return deferred; | |
}; | |
deferred.schedule = deferred; | |
deferred.call = function () { | |
this.cancel(); | |
fcn(); | |
return deferred; | |
}; | |
deferred.cancel = function () { | |
clearTimeout(timer); | |
timer = null; | |
return deferred; | |
}; | |
deferred.isPending = function () { | |
return timer; | |
}; | |
return deferred; | |
}; | |
exports.delayedCall = function (fcn, defaultTimeout) { | |
var timer = null; | |
var callback = function () { | |
timer = null; | |
fcn(); | |
}; | |
var _self = function (timeout) { | |
if (timer == null) | |
timer = setTimeout(callback, timeout || defaultTimeout); | |
}; | |
_self.delay = function (timeout) { | |
timer && clearTimeout(timer); | |
timer = setTimeout(callback, timeout || defaultTimeout); | |
}; | |
_self.schedule = _self; | |
_self.call = function () { | |
this.cancel(); | |
fcn(); | |
}; | |
_self.cancel = function () { | |
timer && clearTimeout(timer); | |
timer = null; | |
}; | |
_self.isPending = function () { | |
return timer; | |
}; | |
return _self; | |
}; | |
exports.supportsLookbehind = function () { | |
try { | |
new RegExp('(?<=.)'); | |
} | |
catch (e) { | |
return false; | |
} | |
return true; | |
}; | |
exports.skipEmptyMatch = function (line, last, supportsUnicodeFlag) { | |
return supportsUnicodeFlag && line.codePointAt(last) > 0xffff ? 2 : 1; | |
}; | |
}); | |
ace.define("ace/worker/mirror", [], function (require, exports, module) { | |
"use strict"; | |
var Document = require("../document").Document; | |
var lang = require("../lib/lang"); | |
var Mirror = exports.Mirror = function (sender) { | |
this.sender = sender; | |
var doc = this.doc = new Document(""); | |
var deferredUpdate = this.deferredUpdate = lang.delayedCall(this.onUpdate.bind(this)); | |
var _self = this; | |
sender.on("change", function (e) { | |
var data = e.data; | |
if (data[0].start) { | |
doc.applyDeltas(data); | |
} else { | |
for (var i = 0; i < data.length; i += 2) { | |
var d, err; | |
if (Array.isArray(data[i + 1])) { | |
d = { action: "insert", start: data[i], lines: data[i + 1] }; | |
} else { | |
d = { action: "remove", start: data[i], end: data[i + 1] }; | |
} | |
if ((d.action == "insert" ? d.start : d.end).row >= doc.$lines.length) { | |
err = new Error("Invalid delta"); | |
err.data = { | |
path: _self.$path, | |
linesLength: doc.$lines.length, | |
start: d.start, | |
end: d.end | |
}; | |
throw err; | |
} | |
doc.applyDelta(d, true); | |
} | |
} | |
if (_self.$timeout) | |
return deferredUpdate.schedule(_self.$timeout); | |
_self.onUpdate(); | |
}); | |
}; | |
(function () { | |
this.$timeout = 500; | |
this.setTimeout = function (timeout) { | |
this.$timeout = timeout; | |
}; | |
this.setValue = function (value) { | |
this.doc.setValue(value); | |
this.deferredUpdate.schedule(this.$timeout); | |
}; | |
this.getValue = function (callbackId) { | |
this.sender.callback(this.doc.getValue(), callbackId); | |
}; | |
this.onUpdate = function () { | |
}; | |
this.isPending = function () { | |
return this.deferredUpdate.isPending(); | |
}; | |
}).call(Mirror.prototype); | |
}); | |
ace.define("ace/mode/toml/toml_parse", [], function (require, exports, module) { | |
'use strict' | |
const ParserEND = 0x110000 | |
class ParserError extends Error { | |
/* istanbul ignore next */ | |
constructor(msg, filename, linenumber) { | |
super('[ParserError] ' + msg, filename, linenumber) | |
this.name = 'ParserError' | |
this.code = 'ParserError' | |
if (Error.captureStackTrace) Error.captureStackTrace(this, ParserError) | |
} | |
} | |
class State { | |
constructor(parser) { | |
this.parser = parser | |
this.buf = '' | |
this.returned = null | |
this.result = null | |
this.resultTable = null | |
this.resultArr = null | |
} | |
} | |
class Parser { | |
constructor() { | |
this.pos = 0 | |
this.col = 0 | |
this.line = 0 | |
this.obj = {} | |
this.ctx = this.obj | |
this.stack = [] | |
this._buf = '' | |
this.char = null | |
this.ii = 0 | |
this.state = new State(this.parseStart) | |
} | |
parse(str) { | |
/* istanbul ignore next */ | |
if (str.length === 0 || str.length == null) return | |
this._buf = String(str) | |
this.ii = -1 | |
this.char = -1 | |
let getNext | |
while (getNext === false || this.nextChar()) { | |
getNext = this.runOne() | |
} | |
this._buf = null | |
} | |
nextChar() { | |
if (this.char === 0x0A) { | |
++this.line | |
this.col = -1 | |
} | |
++this.ii | |
this.char = this._buf.codePointAt(this.ii) | |
++this.pos | |
++this.col | |
return this.haveBuffer() | |
} | |
haveBuffer() { | |
return this.ii < this._buf.length | |
} | |
runOne() { | |
return this.state.parser.call(this, this.state.returned) | |
} | |
finish() { | |
this.char = ParserEND | |
let last | |
do { | |
last = this.state.parser | |
this.runOne() | |
} while (this.state.parser !== last) | |
this.ctx = null | |
this.state = null | |
this._buf = null | |
return this.obj | |
} | |
next(fn) { | |
/* istanbul ignore next */ | |
if (typeof fn !== 'function') throw new ParserError('Tried to set state to non-existent state: ' + JSON.stringify(fn)) | |
this.state.parser = fn | |
} | |
goto(fn) { | |
this.next(fn) | |
return this.runOne() | |
} | |
call(fn, returnWith) { | |
if (returnWith) this.next(returnWith) | |
this.stack.push(this.state) | |
this.state = new State(fn) | |
} | |
callNow(fn, returnWith) { | |
this.call(fn, returnWith) | |
return this.runOne() | |
} | |
return(value) { | |
/* istanbul ignore next */ | |
if (this.stack.length === 0) throw this.error(new ParserError('Stack underflow')) | |
if (value === undefined) value = this.state.buf | |
this.state = this.stack.pop() | |
this.state.returned = value | |
} | |
returnNow(value) { | |
this.return(value) | |
return this.runOne() | |
} | |
consume() { | |
/* istanbul ignore next */ | |
if (this.char === ParserEND) throw this.error(new ParserError('Unexpected end-of-buffer')) | |
this.state.buf += this._buf[this.ii] | |
} | |
error(err) { | |
err.line = this.line | |
err.col = this.col | |
err.pos = this.pos | |
return err | |
} | |
/* istanbul ignore next */ | |
parseStart() { | |
throw new ParserError('Must declare a parseStart method') | |
} | |
} | |
Parser.END = ParserEND | |
Parser.Error = ParserError | |
function f(d, num) { | |
num = String(num) | |
while (num.length < d) num = '0' + num | |
return num | |
} | |
class TomlError extends Error { | |
constructor(msg) { | |
super(msg) | |
this.name = 'TomlError' | |
/* istanbul ignore next */ | |
if (Error.captureStackTrace) Error.captureStackTrace(this, TomlError) | |
this.fromTOML = true | |
this.wrapped = null | |
} | |
} | |
TomlError.wrap = err => { | |
const terr = new TomlError(err.message) | |
terr.code = err.code | |
terr.wrapped = err | |
return terr | |
} | |
const createDateTime = value => { | |
const date = new Date(value) | |
/* istanbul ignore if */ | |
if (isNaN(date)) { | |
throw new TypeError('Invalid Datetime') | |
} else { | |
return date | |
} | |
} | |
class FloatingDateTime extends Date { | |
constructor(value) { | |
super(value + 'Z') | |
this.isFloating = true | |
} | |
toISOString() { | |
const date = `${this.getUTCFullYear()}-${f(2, this.getUTCMonth() + 1)}-${f(2, this.getUTCDate())}` | |
const time = `${f(2, this.getUTCHours())}:${f(2, this.getUTCMinutes())}:${f(2, this.getUTCSeconds())}.${f(3, this.getUTCMilliseconds())}` | |
return `${date}T${time}` | |
} | |
} | |
const createDateTimeFloat = value => { | |
const date = new FloatingDateTime(value) | |
/* istanbul ignore if */ | |
if (isNaN(date)) { | |
throw new TypeError('Invalid Datetime') | |
} else { | |
return date | |
} | |
} | |
class NewDate extends Date { | |
constructor(value) { | |
super(value) | |
this.isDate = true | |
} | |
toISOString() { | |
return `${this.getUTCFullYear()}-${f(2, this.getUTCMonth() + 1)}-${f(2, this.getUTCDate())}` | |
} | |
} | |
const createDate = value => { | |
const date = new NewDate(value) | |
/* istanbul ignore if */ | |
if (isNaN(date)) { | |
throw new TypeError('Invalid Datetime') | |
} else { | |
return date | |
} | |
} | |
class Time extends Date { | |
constructor(value) { | |
super(`0000-01-01T${value}Z`) | |
this.isTime = true | |
} | |
toISOString() { | |
return `${f(2, this.getUTCHours())}:${f(2, this.getUTCMinutes())}:${f(2, this.getUTCSeconds())}.${f(3, this.getUTCMilliseconds())}` | |
} | |
} | |
const createTime = value => { | |
const date = new Time(value) | |
/* istanbul ignore if */ | |
if (isNaN(date)) { | |
throw new TypeError('Invalid Datetime') | |
} else { | |
return date | |
} | |
} | |
const CTRL_I = 0x09 | |
const CTRL_J = 0x0A | |
const CTRL_M = 0x0D | |
const CTRL_CHAR_BOUNDARY = 0x1F // the last non-character in the latin1 region of unicode, except DEL | |
const CHAR_SP = 0x20 | |
const CHAR_QUOT = 0x22 | |
const CHAR_NUM = 0x23 | |
const CHAR_APOS = 0x27 | |
const CHAR_PLUS = 0x2B | |
const CHAR_COMMA = 0x2C | |
const CHAR_HYPHEN = 0x2D | |
const CHAR_PERIOD = 0x2E | |
const CHAR_0 = 0x30 | |
const CHAR_1 = 0x31 | |
const CHAR_7 = 0x37 | |
const CHAR_9 = 0x39 | |
const CHAR_COLON = 0x3A | |
const CHAR_EQUALS = 0x3D | |
const CHAR_A = 0x41 | |
const CHAR_E = 0x45 | |
const CHAR_F = 0x46 | |
const CHAR_T = 0x54 | |
const CHAR_U = 0x55 | |
const CHAR_Z = 0x5A | |
const CHAR_LOWBAR = 0x5F | |
const CHAR_a = 0x61 | |
const CHAR_b = 0x62 | |
const CHAR_e = 0x65 | |
const CHAR_f = 0x66 | |
const CHAR_i = 0x69 | |
const CHAR_l = 0x6C | |
const CHAR_n = 0x6E | |
const CHAR_o = 0x6F | |
const CHAR_r = 0x72 | |
const CHAR_s = 0x73 | |
const CHAR_t = 0x74 | |
const CHAR_u = 0x75 | |
const CHAR_x = 0x78 | |
const CHAR_z = 0x7A | |
const CHAR_LCUB = 0x7B | |
const CHAR_RCUB = 0x7D | |
const CHAR_LSQB = 0x5B | |
const CHAR_BSOL = 0x5C | |
const CHAR_RSQB = 0x5D | |
const CHAR_DEL = 0x7F | |
const SURROGATE_FIRST = 0xD800 | |
const SURROGATE_LAST = 0xDFFF | |
const escapes = { | |
[CHAR_b]: '\u0008', | |
[CHAR_t]: '\u0009', | |
[CHAR_n]: '\u000A', | |
[CHAR_f]: '\u000C', | |
[CHAR_r]: '\u000D', | |
[CHAR_QUOT]: '\u0022', | |
[CHAR_BSOL]: '\u005C' | |
} | |
function isDigit(cp) { | |
return cp >= CHAR_0 && cp <= CHAR_9 | |
} | |
function isHexit(cp) { | |
return (cp >= CHAR_A && cp <= CHAR_F) || (cp >= CHAR_a && cp <= CHAR_f) || (cp >= CHAR_0 && cp <= CHAR_9) | |
} | |
function isBit(cp) { | |
return cp === CHAR_1 || cp === CHAR_0 | |
} | |
function isOctit(cp) { | |
return (cp >= CHAR_0 && cp <= CHAR_7) | |
} | |
function isAlphaNumQuoteHyphen(cp) { | |
return (cp >= CHAR_A && cp <= CHAR_Z) | |
|| (cp >= CHAR_a && cp <= CHAR_z) | |
|| (cp >= CHAR_0 && cp <= CHAR_9) | |
|| cp === CHAR_APOS | |
|| cp === CHAR_QUOT | |
|| cp === CHAR_LOWBAR | |
|| cp === CHAR_HYPHEN | |
} | |
function isAlphaNumHyphen(cp) { | |
return (cp >= CHAR_A && cp <= CHAR_Z) | |
|| (cp >= CHAR_a && cp <= CHAR_z) | |
|| (cp >= CHAR_0 && cp <= CHAR_9) | |
|| cp === CHAR_LOWBAR | |
|| cp === CHAR_HYPHEN | |
} | |
const _type = Symbol('type') | |
const _declared = Symbol('declared') | |
const hasOwnProperty = Object.prototype.hasOwnProperty | |
const defineProperty = Object.defineProperty | |
const descriptor = { configurable: true, enumerable: true, writable: true, value: undefined } | |
function hasKey(obj, key) { | |
if (hasOwnProperty.call(obj, key)) return true | |
if (key === '__proto__') defineProperty(obj, '__proto__', descriptor) | |
return false | |
} | |
const INLINE_TABLE = Symbol('inline-table') | |
function InlineTable() { | |
return Object.defineProperties({}, { | |
[_type]: { value: INLINE_TABLE } | |
}) | |
} | |
function isInlineTable(obj) { | |
if (obj === null || typeof (obj) !== 'object') return false | |
return obj[_type] === INLINE_TABLE | |
} | |
const TABLE = Symbol('table') | |
function Table() { | |
return Object.defineProperties({}, { | |
[_type]: { value: TABLE }, | |
[_declared]: { value: false, writable: true } | |
}) | |
} | |
function isTable(obj) { | |
if (obj === null || typeof (obj) !== 'object') return false | |
return obj[_type] === TABLE | |
} | |
const _contentType = Symbol('content-type') | |
const INLINE_LIST = Symbol('inline-list') | |
function InlineList(type) { | |
return Object.defineProperties([], { | |
[_type]: { value: INLINE_LIST }, | |
[_contentType]: { value: type } | |
}) | |
} | |
function isInlineList(obj) { | |
if (obj === null || typeof (obj) !== 'object') return false | |
return obj[_type] === INLINE_LIST | |
} | |
const LIST = Symbol('list') | |
function List() { | |
return Object.defineProperties([], { | |
[_type]: { value: LIST } | |
}) | |
} | |
function isList(obj) { | |
if (obj === null || typeof (obj) !== 'object') return false | |
return obj[_type] === LIST | |
} | |
// in an eval, to let bundlers not slurp in a util proxy | |
let _custom | |
try { | |
const utilInspect = eval("require('util').inspect") | |
_custom = utilInspect.custom | |
} catch (_) { | |
/* eval require not available in transpiled bundle */ | |
} | |
/* istanbul ignore next */ | |
const _inspect = _custom || 'inspect' | |
class BoxedBigInt { | |
constructor(value) { | |
try { | |
this.value = BigInt.asIntN(64, value) | |
} catch (_) { | |
/* istanbul ignore next */ | |
this.value = null | |
} | |
Object.defineProperty(this, _type, { value: INTEGER }) | |
} | |
isNaN() { | |
return this.value === null | |
} | |
/* istanbul ignore next */ | |
toString() { | |
return String(this.value) | |
} | |
/* istanbul ignore next */ | |
[_inspect]() { | |
return `[BigInt: ${this.toString()}]}` | |
} | |
valueOf() { | |
return this.value | |
} | |
} | |
const INTEGER = Symbol('integer') | |
function Integer(value) { | |
let num = Number(value) | |
// -0 is a float thing, not an int thing | |
if (Object.is(num, -0)) num = 0 | |
/* istanbul ignore else */ | |
if (BigInt && !Number.isSafeInteger(num)) { | |
return new BoxedBigInt(value) | |
} else { | |
/* istanbul ignore next */ | |
return Object.defineProperties(new Number(num), { | |
isNaN: { value: function () { return isNaN(this) } }, | |
[_type]: { value: INTEGER }, | |
[_inspect]: { value: () => `[Integer: ${value}]` } | |
}) | |
} | |
} | |
function isInteger(obj) { | |
if (obj === null || typeof (obj) !== 'object') return false | |
return obj[_type] === INTEGER | |
} | |
const FLOAT = Symbol('float') | |
function Float(value) { | |
/* istanbul ignore next */ | |
return Object.defineProperties(new Number(value), { | |
[_type]: { value: FLOAT }, | |
[_inspect]: { value: () => `[Float: ${value}]` } | |
}) | |
} | |
function isFloat(obj) { | |
if (obj === null || typeof (obj) !== 'object') return false | |
return obj[_type] === FLOAT | |
} | |
function tomlType(value) { | |
const type = typeof value | |
if (type === 'object') { | |
/* istanbul ignore if */ | |
if (value === null) return 'null' | |
if (value instanceof Date) return 'datetime' | |
/* istanbul ignore else */ | |
if (_type in value) { | |
switch (value[_type]) { | |
case INLINE_TABLE: return 'inline-table' | |
case INLINE_LIST: return 'inline-list' | |
/* istanbul ignore next */ | |
case TABLE: return 'table' | |
/* istanbul ignore next */ | |
case LIST: return 'list' | |
case FLOAT: return 'float' | |
case INTEGER: return 'integer' | |
} | |
} | |
} | |
return type | |
} | |
function makeParserClass(Parser) { | |
class TOMLParser extends Parser { | |
constructor() { | |
super() | |
this.ctx = this.obj = Table() | |
} | |
/* MATCH HELPER */ | |
atEndOfWord() { | |
return this.char === CHAR_NUM || this.char === CTRL_I || this.char === CHAR_SP || this.atEndOfLine() | |
} | |
atEndOfLine() { | |
return this.char === Parser.END || this.char === CTRL_J || this.char === CTRL_M | |
} | |
parseStart() { | |
if (this.char === Parser.END) { | |
return null | |
} else if (this.char === CHAR_LSQB) { | |
return this.call(this.parseTableOrList) | |
} else if (this.char === CHAR_NUM) { | |
return this.call(this.parseComment) | |
} else if (this.char === CTRL_J || this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M) { | |
return null | |
} else if (isAlphaNumQuoteHyphen(this.char)) { | |
return this.callNow(this.parseAssignStatement) | |
} else { | |
throw this.error(new TomlError(`Unknown character "${this.char}"`)) | |
} | |
} | |
// HELPER, this strips any whitespace and comments to the end of the line | |
// then RETURNS. Last state in a production. | |
parseWhitespaceToEOL() { | |
if (this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M) { | |
return null | |
} else if (this.char === CHAR_NUM) { | |
return this.goto(this.parseComment) | |
} else if (this.char === Parser.END || this.char === CTRL_J) { | |
return this.return() | |
} else { | |
throw this.error(new TomlError('Unexpected character, expected only whitespace or comments till end of line')) | |
} | |
} | |
/* ASSIGNMENT: key = value */ | |
parseAssignStatement() { | |
return this.callNow(this.parseAssign, this.recordAssignStatement) | |
} | |
recordAssignStatement(kv) { | |
let target = this.ctx | |
let finalKey = kv.key.pop() | |
for (let kw of kv.key) { | |
if (hasKey(target, kw) && !isTable(target[kw])) { | |
throw this.error(new TomlError("Can't redefine existing key")) | |
} | |
target = target[kw] = target[kw] || Table() | |
} | |
if (hasKey(target, finalKey)) { | |
throw this.error(new TomlError("Can't redefine existing key")) | |
} | |
target[_declared] = true | |
// unbox our numbers | |
if (isInteger(kv.value) || isFloat(kv.value)) { | |
target[finalKey] = kv.value.valueOf() | |
} else { | |
target[finalKey] = kv.value | |
} | |
return this.goto(this.parseWhitespaceToEOL) | |
} | |
/* ASSSIGNMENT expression, key = value possibly inside an inline table */ | |
parseAssign() { | |
return this.callNow(this.parseKeyword, this.recordAssignKeyword) | |
} | |
recordAssignKeyword(key) { | |
if (this.state.resultTable) { | |
this.state.resultTable.push(key) | |
} else { | |
this.state.resultTable = [key] | |
} | |
return this.goto(this.parseAssignKeywordPreDot) | |
} | |
parseAssignKeywordPreDot() { | |
if (this.char === CHAR_PERIOD) { | |
return this.next(this.parseAssignKeywordPostDot) | |
} else if (this.char !== CHAR_SP && this.char !== CTRL_I) { | |
return this.goto(this.parseAssignEqual) | |
} | |
} | |
parseAssignKeywordPostDot() { | |
if (this.char !== CHAR_SP && this.char !== CTRL_I) { | |
return this.callNow(this.parseKeyword, this.recordAssignKeyword) | |
} | |
} | |
parseAssignEqual() { | |
if (this.char === CHAR_EQUALS) { | |
return this.next(this.parseAssignPreValue) | |
} else { | |
throw this.error(new TomlError('Invalid character, expected "="')) | |
} | |
} | |
parseAssignPreValue() { | |
if (this.char === CHAR_SP || this.char === CTRL_I) { | |
return null | |
} else { | |
return this.callNow(this.parseValue, this.recordAssignValue) | |
} | |
} | |
recordAssignValue(value) { | |
return this.returnNow({ key: this.state.resultTable, value: value }) | |
} | |
/* COMMENTS: #...eol */ | |
parseComment() { | |
do { | |
if (this.char === Parser.END || this.char === CTRL_J) { | |
return this.return() | |
} else if (this.char === CHAR_DEL || (this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I)) { | |
throw this.errorControlCharIn('comments') | |
} | |
} while (this.nextChar()) | |
} | |
/* TABLES AND LISTS, [foo] and [[foo]] */ | |
parseTableOrList() { | |
if (this.char === CHAR_LSQB) { | |
this.next(this.parseList) | |
} else { | |
return this.goto(this.parseTable) | |
} | |
} | |
/* TABLE [foo.bar.baz] */ | |
parseTable() { | |
this.ctx = this.obj | |
return this.goto(this.parseTableNext) | |
} | |
parseTableNext() { | |
if (this.char === CHAR_SP || this.char === CTRL_I) { | |
return null | |
} else { | |
return this.callNow(this.parseKeyword, this.parseTableMore) | |
} | |
} | |
parseTableMore(keyword) { | |
if (this.char === CHAR_SP || this.char === CTRL_I) { | |
return null | |
} else if (this.char === CHAR_RSQB) { | |
if (hasKey(this.ctx, keyword) && (!isTable(this.ctx[keyword]) || this.ctx[keyword][_declared])) { | |
throw this.error(new TomlError("Can't redefine existing key")) | |
} else { | |
this.ctx = this.ctx[keyword] = this.ctx[keyword] || Table() | |
this.ctx[_declared] = true | |
} | |
return this.next(this.parseWhitespaceToEOL) | |
} else if (this.char === CHAR_PERIOD) { | |
if (!hasKey(this.ctx, keyword)) { | |
this.ctx = this.ctx[keyword] = Table() | |
} else if (isTable(this.ctx[keyword])) { | |
this.ctx = this.ctx[keyword] | |
} else if (isList(this.ctx[keyword])) { | |
this.ctx = this.ctx[keyword][this.ctx[keyword].length - 1] | |
} else { | |
throw this.error(new TomlError("Can't redefine existing key")) | |
} | |
return this.next(this.parseTableNext) | |
} else { | |
throw this.error(new TomlError('Unexpected character, expected whitespace, . or ]')) | |
} | |
} | |
/* LIST [[a.b.c]] */ | |
parseList() { | |
this.ctx = this.obj | |
return this.goto(this.parseListNext) | |
} | |
parseListNext() { | |
if (this.char === CHAR_SP || this.char === CTRL_I) { | |
return null | |
} else { | |
return this.callNow(this.parseKeyword, this.parseListMore) | |
} | |
} | |
parseListMore(keyword) { | |
if (this.char === CHAR_SP || this.char === CTRL_I) { | |
return null | |
} else if (this.char === CHAR_RSQB) { | |
if (!hasKey(this.ctx, keyword)) { | |
this.ctx[keyword] = List() | |
} | |
if (isInlineList(this.ctx[keyword])) { | |
throw this.error(new TomlError("Can't extend an inline array")) | |
} else if (isList(this.ctx[keyword])) { | |
const next = Table() | |
this.ctx[keyword].push(next) | |
this.ctx = next | |
} else { | |
throw this.error(new TomlError("Can't redefine an existing key")) | |
} | |
return this.next(this.parseListEnd) | |
} else if (this.char === CHAR_PERIOD) { | |
if (!hasKey(this.ctx, keyword)) { | |
this.ctx = this.ctx[keyword] = Table() | |
} else if (isInlineList(this.ctx[keyword])) { | |
throw this.error(new TomlError("Can't extend an inline array")) | |
} else if (isInlineTable(this.ctx[keyword])) { | |
throw this.error(new TomlError("Can't extend an inline table")) | |
} else if (isList(this.ctx[keyword])) { | |
this.ctx = this.ctx[keyword][this.ctx[keyword].length - 1] | |
} else if (isTable(this.ctx[keyword])) { | |
this.ctx = this.ctx[keyword] | |
} else { | |
throw this.error(new TomlError("Can't redefine an existing key")) | |
} | |
return this.next(this.parseListNext) | |
} else { | |
throw this.error(new TomlError('Unexpected character, expected whitespace, . or ]')) | |
} | |
} | |
parseListEnd(keyword) { | |
if (this.char === CHAR_RSQB) { | |
return this.next(this.parseWhitespaceToEOL) | |
} else { | |
throw this.error(new TomlError('Unexpected character, expected whitespace, . or ]')) | |
} | |
} | |
/* VALUE string, number, boolean, inline list, inline object */ | |
parseValue() { | |
if (this.char === Parser.END) { | |
throw this.error(new TomlError('Key without value')) | |
} else if (this.char === CHAR_QUOT) { | |
return this.next(this.parseDoubleString) | |
} if (this.char === CHAR_APOS) { | |
return this.next(this.parseSingleString) | |
} else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) { | |
return this.goto(this.parseNumberSign) | |
} else if (this.char === CHAR_i) { | |
return this.next(this.parseInf) | |
} else if (this.char === CHAR_n) { | |
return this.next(this.parseNan) | |
} else if (isDigit(this.char)) { | |
return this.goto(this.parseNumberOrDateTime) | |
} else if (this.char === CHAR_t || this.char === CHAR_f) { | |
return this.goto(this.parseBoolean) | |
} else if (this.char === CHAR_LSQB) { | |
return this.call(this.parseInlineList, this.recordValue) | |
} else if (this.char === CHAR_LCUB) { | |
return this.call(this.parseInlineTable, this.recordValue) | |
} else { | |
throw this.error(new TomlError('Unexpected character, expecting string, number, datetime, boolean, inline array or inline table')) | |
} | |
} | |
recordValue(value) { | |
return this.returnNow(value) | |
} | |
parseInf() { | |
if (this.char === CHAR_n) { | |
return this.next(this.parseInf2) | |
} else { | |
throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"')) | |
} | |
} | |
parseInf2() { | |
if (this.char === CHAR_f) { | |
if (this.state.buf === '-') { | |
return this.return(-Infinity) | |
} else { | |
return this.return(Infinity) | |
} | |
} else { | |
throw this.error(new TomlError('Unexpected character, expected "inf", "+inf" or "-inf"')) | |
} | |
} | |
parseNan() { | |
if (this.char === CHAR_a) { | |
return this.next(this.parseNan2) | |
} else { | |
throw this.error(new TomlError('Unexpected character, expected "nan"')) | |
} | |
} | |
parseNan2() { | |
if (this.char === CHAR_n) { | |
return this.return(NaN) | |
} else { | |
throw this.error(new TomlError('Unexpected character, expected "nan"')) | |
} | |
} | |
/* KEYS, barewords or basic, literal, or dotted */ | |
parseKeyword() { | |
if (this.char === CHAR_QUOT) { | |
return this.next(this.parseBasicString) | |
} else if (this.char === CHAR_APOS) { | |
return this.next(this.parseLiteralString) | |
} else { | |
return this.goto(this.parseBareKey) | |
} | |
} | |
/* KEYS: barewords */ | |
parseBareKey() { | |
do { | |
if (this.char === Parser.END) { | |
throw this.error(new TomlError('Key ended without value')) | |
} else if (isAlphaNumHyphen(this.char)) { | |
this.consume() | |
} else if (this.state.buf.length === 0) { | |
throw this.error(new TomlError('Empty bare keys are not allowed')) | |
} else { | |
return this.returnNow() | |
} | |
} while (this.nextChar()) | |
} | |
/* STRINGS, single quoted (literal) */ | |
parseSingleString() { | |
if (this.char === CHAR_APOS) { | |
return this.next(this.parseLiteralMultiStringMaybe) | |
} else { | |
return this.goto(this.parseLiteralString) | |
} | |
} | |
parseLiteralString() { | |
do { | |
if (this.char === CHAR_APOS) { | |
return this.return() | |
} else if (this.atEndOfLine()) { | |
throw this.error(new TomlError('Unterminated string')) | |
} else if (this.char === CHAR_DEL || (this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I)) { | |
throw this.errorControlCharIn('strings') | |
} else { | |
this.consume() | |
} | |
} while (this.nextChar()) | |
} | |
parseLiteralMultiStringMaybe() { | |
if (this.char === CHAR_APOS) { | |
return this.next(this.parseLiteralMultiString) | |
} else { | |
return this.returnNow() | |
} | |
} | |
parseLiteralMultiString() { | |
if (this.char === CTRL_M) { | |
return null | |
} else if (this.char === CTRL_J) { | |
return this.next(this.parseLiteralMultiStringContent) | |
} else { | |
return this.goto(this.parseLiteralMultiStringContent) | |
} | |
} | |
parseLiteralMultiStringContent() { | |
do { | |
if (this.char === CHAR_APOS) { | |
return this.next(this.parseLiteralMultiEnd) | |
} else if (this.char === Parser.END) { | |
throw this.error(new TomlError('Unterminated multi-line string')) | |
} else if (this.char === CHAR_DEL || (this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I && this.char !== CTRL_J && this.char !== CTRL_M)) { | |
throw this.errorControlCharIn('strings') | |
} else { | |
this.consume() | |
} | |
} while (this.nextChar()) | |
} | |
parseLiteralMultiEnd() { | |
if (this.char === CHAR_APOS) { | |
return this.next(this.parseLiteralMultiEnd2) | |
} else { | |
this.state.buf += "'" | |
return this.goto(this.parseLiteralMultiStringContent) | |
} | |
} | |
parseLiteralMultiEnd2() { | |
if (this.char === CHAR_APOS) { | |
return this.next(this.parseLiteralMultiEnd3) | |
} else { | |
this.state.buf += "''" | |
return this.goto(this.parseLiteralMultiStringContent) | |
} | |
} | |
parseLiteralMultiEnd3() { | |
if (this.char === CHAR_APOS) { | |
this.state.buf += "'" | |
return this.next(this.parseLiteralMultiEnd4) | |
} else { | |
return this.returnNow() | |
} | |
} | |
parseLiteralMultiEnd4() { | |
if (this.char === CHAR_APOS) { | |
this.state.buf += "'" | |
return this.return() | |
} else { | |
return this.returnNow() | |
} | |
} | |
/* STRINGS double quoted */ | |
parseDoubleString() { | |
if (this.char === CHAR_QUOT) { | |
return this.next(this.parseMultiStringMaybe) | |
} else { | |
return this.goto(this.parseBasicString) | |
} | |
} | |
parseBasicString() { | |
do { | |
if (this.char === CHAR_BSOL) { | |
return this.call(this.parseEscape, this.recordEscapeReplacement) | |
} else if (this.char === CHAR_QUOT) { | |
return this.return() | |
} else if (this.atEndOfLine()) { | |
throw this.error(new TomlError('Unterminated string')) | |
} else if (this.char === CHAR_DEL || (this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I)) { | |
throw this.errorControlCharIn('strings') | |
} else { | |
this.consume() | |
} | |
} while (this.nextChar()) | |
} | |
recordEscapeReplacement(replacement) { | |
this.state.buf += replacement | |
return this.goto(this.parseBasicString) | |
} | |
parseMultiStringMaybe() { | |
if (this.char === CHAR_QUOT) { | |
return this.next(this.parseMultiString) | |
} else { | |
return this.returnNow() | |
} | |
} | |
parseMultiString() { | |
if (this.char === CTRL_M) { | |
return null | |
} else if (this.char === CTRL_J) { | |
return this.next(this.parseMultiStringContent) | |
} else { | |
return this.goto(this.parseMultiStringContent) | |
} | |
} | |
parseMultiStringContent() { | |
do { | |
if (this.char === CHAR_BSOL) { | |
return this.call(this.parseMultiEscape, this.recordMultiEscapeReplacement) | |
} else if (this.char === CHAR_QUOT) { | |
return this.next(this.parseMultiEnd) | |
} else if (this.char === Parser.END) { | |
throw this.error(new TomlError('Unterminated multi-line string')) | |
} else if (this.char === CHAR_DEL || (this.char <= CTRL_CHAR_BOUNDARY && this.char !== CTRL_I && this.char !== CTRL_J && this.char !== CTRL_M)) { | |
throw this.errorControlCharIn('strings') | |
} else { | |
this.consume() | |
} | |
} while (this.nextChar()) | |
} | |
errorControlCharIn(type) { | |
let displayCode = '\\u00' | |
if (this.char < 16) { | |
displayCode += '0' | |
} | |
displayCode += this.char.toString(16) | |
return this.error(new TomlError(`Control characters (codes < 0x1f and 0x7f) are not allowed in ${type}, use ${displayCode} instead`)) | |
} | |
recordMultiEscapeReplacement(replacement) { | |
this.state.buf += replacement | |
return this.goto(this.parseMultiStringContent) | |
} | |
parseMultiEnd() { | |
if (this.char === CHAR_QUOT) { | |
return this.next(this.parseMultiEnd2) | |
} else { | |
this.state.buf += '"' | |
return this.goto(this.parseMultiStringContent) | |
} | |
} | |
parseMultiEnd2() { | |
if (this.char === CHAR_QUOT) { | |
return this.next(this.parseMultiEnd3) | |
} else { | |
this.state.buf += '""' | |
return this.goto(this.parseMultiStringContent) | |
} | |
} | |
parseMultiEnd3() { | |
if (this.char === CHAR_QUOT) { | |
this.state.buf += '"' | |
return this.next(this.parseMultiEnd4) | |
} else { | |
return this.returnNow() | |
} | |
} | |
parseMultiEnd4() { | |
if (this.char === CHAR_QUOT) { | |
this.state.buf += '"' | |
return this.return() | |
} else { | |
return this.returnNow() | |
} | |
} | |
parseMultiEscape() { | |
if (this.char === CTRL_M || this.char === CTRL_J) { | |
return this.next(this.parseMultiTrim) | |
} else if (this.char === CHAR_SP || this.char === CTRL_I) { | |
return this.next(this.parsePreMultiTrim) | |
} else { | |
return this.goto(this.parseEscape) | |
} | |
} | |
parsePreMultiTrim() { | |
if (this.char === CHAR_SP || this.char === CTRL_I) { | |
return null | |
} else if (this.char === CTRL_M || this.char === CTRL_J) { | |
return this.next(this.parseMultiTrim) | |
} else { | |
throw this.error(new TomlError("Can't escape whitespace")) | |
} | |
} | |
parseMultiTrim() { | |
// explicitly whitespace here, END should follow the same path as chars | |
if (this.char === CTRL_J || this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M) { | |
return null | |
} else { | |
return this.returnNow() | |
} | |
} | |
parseEscape() { | |
if (this.char in escapes) { | |
return this.return(escapes[this.char]) | |
} else if (this.char === CHAR_u) { | |
return this.call(this.parseSmallUnicode, this.parseUnicodeReturn) | |
} else if (this.char === CHAR_U) { | |
return this.call(this.parseLargeUnicode, this.parseUnicodeReturn) | |
} else { | |
throw this.error(new TomlError('Unknown escape character: ' + this.char)) | |
} | |
} | |
parseUnicodeReturn(char) { | |
try { | |
const codePoint = parseInt(char, 16) | |
if (codePoint >= SURROGATE_FIRST && codePoint <= SURROGATE_LAST) { | |
throw this.error(new TomlError('Invalid unicode, character in range 0xD800 - 0xDFFF is reserved')) | |
} | |
return this.returnNow(String.fromCodePoint(codePoint)) | |
} catch (err) { | |
throw this.error(TomlError.wrap(err)) | |
} | |
} | |
parseSmallUnicode() { | |
if (!isHexit(this.char)) { | |
throw this.error(new TomlError('Invalid character in unicode sequence, expected hex')) | |
} else { | |
this.consume() | |
if (this.state.buf.length >= 4) return this.return() | |
} | |
} | |
parseLargeUnicode() { | |
if (!isHexit(this.char)) { | |
throw this.error(new TomlError('Invalid character in unicode sequence, expected hex')) | |
} else { | |
this.consume() | |
if (this.state.buf.length >= 8) return this.return() | |
} | |
} | |
/* NUMBERS */ | |
parseNumberSign() { | |
this.consume() | |
return this.next(this.parseMaybeSignedInfOrNan) | |
} | |
parseMaybeSignedInfOrNan() { | |
if (this.char === CHAR_i) { | |
return this.next(this.parseInf) | |
} else if (this.char === CHAR_n) { | |
return this.next(this.parseNan) | |
} else { | |
return this.callNow(this.parseNoUnder, this.parseNumberIntegerStart) | |
} | |
} | |
parseNumberIntegerStart() { | |
if (this.char === CHAR_0) { | |
this.consume() | |
return this.next(this.parseNumberIntegerExponentOrDecimal) | |
} else { | |
return this.goto(this.parseNumberInteger) | |
} | |
} | |
parseNumberIntegerExponentOrDecimal() { | |
if (this.char === CHAR_PERIOD) { | |
this.consume() | |
return this.call(this.parseNoUnder, this.parseNumberFloat) | |
} else if (this.char === CHAR_E || this.char === CHAR_e) { | |
this.consume() | |
return this.next(this.parseNumberExponentSign) | |
} else { | |
return this.returnNow(Integer(this.state.buf)) | |
} | |
} | |
parseNumberInteger() { | |
if (isDigit(this.char)) { | |
this.consume() | |
} else if (this.char === CHAR_LOWBAR) { | |
return this.call(this.parseNoUnder) | |
} else if (this.char === CHAR_E || this.char === CHAR_e) { | |
this.consume() | |
return this.next(this.parseNumberExponentSign) | |
} else if (this.char === CHAR_PERIOD) { | |
this.consume() | |
return this.call(this.parseNoUnder, this.parseNumberFloat) | |
} else { | |
const result = Integer(this.state.buf) | |
/* istanbul ignore if */ | |
if (result.isNaN()) { | |
throw this.error(new TomlError('Invalid number')) | |
} else { | |
return this.returnNow(result) | |
} | |
} | |
} | |
parseNoUnder() { | |
if (this.char === CHAR_LOWBAR || this.char === CHAR_PERIOD || this.char === CHAR_E || this.char === CHAR_e) { | |
throw this.error(new TomlError('Unexpected character, expected digit')) | |
} else if (this.atEndOfWord()) { | |
throw this.error(new TomlError('Incomplete number')) | |
} | |
return this.returnNow() | |
} | |
parseNoUnderHexOctBinLiteral() { | |
if (this.char === CHAR_LOWBAR || this.char === CHAR_PERIOD) { | |
throw this.error(new TomlError('Unexpected character, expected digit')) | |
} else if (this.atEndOfWord()) { | |
throw this.error(new TomlError('Incomplete number')) | |
} | |
return this.returnNow() | |
} | |
parseNumberFloat() { | |
if (this.char === CHAR_LOWBAR) { | |
return this.call(this.parseNoUnder, this.parseNumberFloat) | |
} else if (isDigit(this.char)) { | |
this.consume() | |
} else if (this.char === CHAR_E || this.char === CHAR_e) { | |
this.consume() | |
return this.next(this.parseNumberExponentSign) | |
} else { | |
return this.returnNow(Float(this.state.buf)) | |
} | |
} | |
parseNumberExponentSign() { | |
if (isDigit(this.char)) { | |
return this.goto(this.parseNumberExponent) | |
} else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) { | |
this.consume() | |
this.call(this.parseNoUnder, this.parseNumberExponent) | |
} else { | |
throw this.error(new TomlError('Unexpected character, expected -, + or digit')) | |
} | |
} | |
parseNumberExponent() { | |
if (isDigit(this.char)) { | |
this.consume() | |
} else if (this.char === CHAR_LOWBAR) { | |
return this.call(this.parseNoUnder) | |
} else { | |
return this.returnNow(Float(this.state.buf)) | |
} | |
} | |
/* NUMBERS or DATETIMES */ | |
parseNumberOrDateTime() { | |
if (this.char === CHAR_0) { | |
this.consume() | |
return this.next(this.parseNumberBaseOrDateTime) | |
} else { | |
return this.goto(this.parseNumberOrDateTimeOnly) | |
} | |
} | |
parseNumberOrDateTimeOnly() { | |
// note, if two zeros are in a row then it MUST be a date | |
if (this.char === CHAR_LOWBAR) { | |
return this.call(this.parseNoUnder, this.parseNumberInteger) | |
} else if (isDigit(this.char)) { | |
this.consume() | |
if (this.state.buf.length > 4) this.next(this.parseNumberInteger) | |
} else if (this.char === CHAR_E || this.char === CHAR_e) { | |
this.consume() | |
return this.next(this.parseNumberExponentSign) | |
} else if (this.char === CHAR_PERIOD) { | |
this.consume() | |
return this.call(this.parseNoUnder, this.parseNumberFloat) | |
} else if (this.char === CHAR_HYPHEN) { | |
return this.goto(this.parseDateTime) | |
} else if (this.char === CHAR_COLON) { | |
return this.goto(this.parseOnlyTimeHour) | |
} else { | |
return this.returnNow(Integer(this.state.buf)) | |
} | |
} | |
parseDateTimeOnly() { | |
if (this.state.buf.length < 4) { | |
if (isDigit(this.char)) { | |
return this.consume() | |
} else if (this.char === CHAR_COLON) { | |
return this.goto(this.parseOnlyTimeHour) | |
} else { | |
throw this.error(new TomlError('Expected digit while parsing year part of a date')) | |
} | |
} else { | |
if (this.char === CHAR_HYPHEN) { | |
return this.goto(this.parseDateTime) | |
} else { | |
throw this.error(new TomlError('Expected hyphen (-) while parsing year part of date')) | |
} | |
} | |
} | |
parseNumberBaseOrDateTime() { | |
if (this.char === CHAR_b) { | |
this.consume() | |
return this.call(this.parseNoUnderHexOctBinLiteral, this.parseIntegerBin) | |
} else if (this.char === CHAR_o) { | |
this.consume() | |
return this.call(this.parseNoUnderHexOctBinLiteral, this.parseIntegerOct) | |
} else if (this.char === CHAR_x) { | |
this.consume() | |
return this.call(this.parseNoUnderHexOctBinLiteral, this.parseIntegerHex) | |
} else if (this.char === CHAR_PERIOD) { | |
return this.goto(this.parseNumberInteger) | |
} else if (isDigit(this.char)) { | |
return this.goto(this.parseDateTimeOnly) | |
} else { | |
return this.returnNow(Integer(this.state.buf)) | |
} | |
} | |
parseIntegerHex() { | |
if (isHexit(this.char)) { | |
this.consume() | |
} else if (this.char === CHAR_LOWBAR) { | |
return this.call(this.parseNoUnderHexOctBinLiteral) | |
} else { | |
const result = Integer(this.state.buf) | |
/* istanbul ignore if */ | |
if (result.isNaN()) { | |
throw this.error(new TomlError('Invalid number')) | |
} else { | |
return this.returnNow(result) | |
} | |
} | |
} | |
parseIntegerOct() { | |
if (isOctit(this.char)) { | |
this.consume() | |
} else if (this.char === CHAR_LOWBAR) { | |
return this.call(this.parseNoUnderHexOctBinLiteral) | |
} else { | |
const result = Integer(this.state.buf) | |
/* istanbul ignore if */ | |
if (result.isNaN()) { | |
throw this.error(new TomlError('Invalid number')) | |
} else { | |
return this.returnNow(result) | |
} | |
} | |
} | |
parseIntegerBin() { | |
if (isBit(this.char)) { | |
this.consume() | |
} else if (this.char === CHAR_LOWBAR) { | |
return this.call(this.parseNoUnderHexOctBinLiteral) | |
} else { | |
const result = Integer(this.state.buf) | |
/* istanbul ignore if */ | |
if (result.isNaN()) { | |
throw this.error(new TomlError('Invalid number')) | |
} else { | |
return this.returnNow(result) | |
} | |
} | |
} | |
/* DATETIME */ | |
parseDateTime() { | |
// we enter here having just consumed the year and about to consume the hyphen | |
if (this.state.buf.length < 4) { | |
throw this.error(new TomlError('Years less than 1000 must be zero padded to four characters')) | |
} | |
this.state.result = this.state.buf | |
this.state.buf = '' | |
return this.next(this.parseDateMonth) | |
} | |
parseDateMonth() { | |
if (this.char === CHAR_HYPHEN) { | |
if (this.state.buf.length < 2) { | |
throw this.error(new TomlError('Months less than 10 must be zero padded to two characters')) | |
} | |
this.state.result += '-' + this.state.buf | |
this.state.buf = '' | |
return this.next(this.parseDateDay) | |
} else if (isDigit(this.char)) { | |
this.consume() | |
} else { | |
throw this.error(new TomlError('Incomplete datetime')) | |
} | |
} | |
parseDateDay() { | |
if (this.char === CHAR_T || this.char === CHAR_SP) { | |
if (this.state.buf.length < 2) { | |
throw this.error(new TomlError('Days less than 10 must be zero padded to two characters')) | |
} | |
this.state.result += '-' + this.state.buf | |
this.state.buf = '' | |
return this.next(this.parseStartTimeHour) | |
} else if (this.atEndOfWord()) { | |
return this.returnNow(createDate(this.state.result + '-' + this.state.buf)) | |
} else if (isDigit(this.char)) { | |
this.consume() | |
} else { | |
throw this.error(new TomlError('Incomplete datetime')) | |
} | |
} | |
parseStartTimeHour() { | |
if (this.atEndOfWord()) { | |
return this.returnNow(createDate(this.state.result)) | |
} else { | |
return this.goto(this.parseTimeHour) | |
} | |
} | |
parseTimeHour() { | |
if (this.char === CHAR_COLON) { | |
if (this.state.buf.length < 2) { | |
throw this.error(new TomlError('Hours less than 10 must be zero padded to two characters')) | |
} | |
this.state.result += 'T' + this.state.buf | |
this.state.buf = '' | |
return this.next(this.parseTimeMin) | |
} else if (isDigit(this.char)) { | |
this.consume() | |
} else { | |
throw this.error(new TomlError('Incomplete datetime')) | |
} | |
} | |
parseTimeMin() { | |
if (this.state.buf.length < 2 && isDigit(this.char)) { | |
this.consume() | |
} else if (this.state.buf.length === 2 && this.char === CHAR_COLON) { | |
this.state.result += ':' + this.state.buf | |
this.state.buf = '' | |
return this.next(this.parseTimeSec) | |
} else { | |
throw this.error(new TomlError('Incomplete datetime')) | |
} | |
} | |
parseTimeSec() { | |
if (isDigit(this.char)) { | |
this.consume() | |
if (this.state.buf.length === 2) { | |
this.state.result += ':' + this.state.buf | |
this.state.buf = '' | |
return this.next(this.parseTimeZoneOrFraction) | |
} | |
} else { | |
throw this.error(new TomlError('Incomplete datetime')) | |
} | |
} | |
parseOnlyTimeHour() { | |
/* istanbul ignore else */ | |
if (this.char === CHAR_COLON) { | |
if (this.state.buf.length < 2) { | |
throw this.error(new TomlError('Hours less than 10 must be zero padded to two characters')) | |
} | |
this.state.result = this.state.buf | |
this.state.buf = '' | |
return this.next(this.parseOnlyTimeMin) | |
} else { | |
throw this.error(new TomlError('Incomplete time')) | |
} | |
} | |
parseOnlyTimeMin() { | |
if (this.state.buf.length < 2 && isDigit(this.char)) { | |
this.consume() | |
} else if (this.state.buf.length === 2 && this.char === CHAR_COLON) { | |
this.state.result += ':' + this.state.buf | |
this.state.buf = '' | |
return this.next(this.parseOnlyTimeSec) | |
} else { | |
throw this.error(new TomlError('Incomplete time')) | |
} | |
} | |
parseOnlyTimeSec() { | |
if (isDigit(this.char)) { | |
this.consume() | |
if (this.state.buf.length === 2) { | |
return this.next(this.parseOnlyTimeFractionMaybe) | |
} | |
} else { | |
throw this.error(new TomlError('Incomplete time')) | |
} | |
} | |
parseOnlyTimeFractionMaybe() { | |
this.state.result += ':' + this.state.buf | |
if (this.char === CHAR_PERIOD) { | |
this.state.buf = '' | |
this.next(this.parseOnlyTimeFraction) | |
} else { | |
return this.return(createTime(this.state.result)) | |
} | |
} | |
parseOnlyTimeFraction() { | |
if (isDigit(this.char)) { | |
this.consume() | |
} else if (this.atEndOfWord()) { | |
if (this.state.buf.length === 0) throw this.error(new TomlError('Expected digit in milliseconds')) | |
return this.returnNow(createTime(this.state.result + '.' + this.state.buf)) | |
} else { | |
throw this.error(new TomlError('Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z')) | |
} | |
} | |
parseTimeZoneOrFraction() { | |
if (this.char === CHAR_PERIOD) { | |
this.consume() | |
this.next(this.parseDateTimeFraction) | |
} else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) { | |
this.consume() | |
this.next(this.parseTimeZoneHour) | |
} else if (this.char === CHAR_Z) { | |
this.consume() | |
return this.return(createDateTime(this.state.result + this.state.buf)) | |
} else if (this.atEndOfWord()) { | |
return this.returnNow(createDateTimeFloat(this.state.result + this.state.buf)) | |
} else { | |
throw this.error(new TomlError('Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z')) | |
} | |
} | |
parseDateTimeFraction() { | |
if (isDigit(this.char)) { | |
this.consume() | |
} else if (this.state.buf.length === 1) { | |
throw this.error(new TomlError('Expected digit in milliseconds')) | |
} else if (this.char === CHAR_HYPHEN || this.char === CHAR_PLUS) { | |
this.consume() | |
this.next(this.parseTimeZoneHour) | |
} else if (this.char === CHAR_Z) { | |
this.consume() | |
return this.return(createDateTime(this.state.result + this.state.buf)) | |
} else if (this.atEndOfWord()) { | |
return this.returnNow(createDateTimeFloat(this.state.result + this.state.buf)) | |
} else { | |
throw this.error(new TomlError('Unexpected character in datetime, expected period (.), minus (-), plus (+) or Z')) | |
} | |
} | |
parseTimeZoneHour() { | |
if (isDigit(this.char)) { | |
this.consume() | |
// FIXME: No more regexps | |
if (/\d\d$/.test(this.state.buf)) return this.next(this.parseTimeZoneSep) | |
} else { | |
throw this.error(new TomlError('Unexpected character in datetime, expected digit')) | |
} | |
} | |
parseTimeZoneSep() { | |
if (this.char === CHAR_COLON) { | |
this.consume() | |
this.next(this.parseTimeZoneMin) | |
} else { | |
throw this.error(new TomlError('Unexpected character in datetime, expected colon')) | |
} | |
} | |
parseTimeZoneMin() { | |
if (isDigit(this.char)) { | |
this.consume() | |
if (/\d\d$/.test(this.state.buf)) return this.return(createDateTime(this.state.result + this.state.buf)) | |
} else { | |
throw this.error(new TomlError('Unexpected character in datetime, expected digit')) | |
} | |
} | |
/* BOOLEAN */ | |
parseBoolean() { | |
/* istanbul ignore else */ | |
if (this.char === CHAR_t) { | |
this.consume() | |
return this.next(this.parseTrue_r) | |
} else if (this.char === CHAR_f) { | |
this.consume() | |
return this.next(this.parseFalse_a) | |
} | |
} | |
parseTrue_r() { | |
if (this.char === CHAR_r) { | |
this.consume() | |
return this.next(this.parseTrue_u) | |
} else { | |
throw this.error(new TomlError('Invalid boolean, expected true or false')) | |
} | |
} | |
parseTrue_u() { | |
if (this.char === CHAR_u) { | |
this.consume() | |
return this.next(this.parseTrue_e) | |
} else { | |
throw this.error(new TomlError('Invalid boolean, expected true or false')) | |
} | |
} | |
parseTrue_e() { | |
if (this.char === CHAR_e) { | |
return this.return(true) | |
} else { | |
throw this.error(new TomlError('Invalid boolean, expected true or false')) | |
} | |
} | |
parseFalse_a() { | |
if (this.char === CHAR_a) { | |
this.consume() | |
return this.next(this.parseFalse_l) | |
} else { | |
throw this.error(new TomlError('Invalid boolean, expected true or false')) | |
} | |
} | |
parseFalse_l() { | |
if (this.char === CHAR_l) { | |
this.consume() | |
return this.next(this.parseFalse_s) | |
} else { | |
throw this.error(new TomlError('Invalid boolean, expected true or false')) | |
} | |
} | |
parseFalse_s() { | |
if (this.char === CHAR_s) { | |
this.consume() | |
return this.next(this.parseFalse_e) | |
} else { | |
throw this.error(new TomlError('Invalid boolean, expected true or false')) | |
} | |
} | |
parseFalse_e() { | |
if (this.char === CHAR_e) { | |
return this.return(false) | |
} else { | |
throw this.error(new TomlError('Invalid boolean, expected true or false')) | |
} | |
} | |
/* INLINE LISTS */ | |
parseInlineList() { | |
if (this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M || this.char === CTRL_J) { | |
return null | |
} else if (this.char === Parser.END) { | |
throw this.error(new TomlError('Unterminated inline array')) | |
} else if (this.char === CHAR_NUM) { | |
return this.call(this.parseComment) | |
} else if (this.char === CHAR_RSQB) { | |
return this.return(this.state.resultArr || InlineList()) | |
} else { | |
return this.callNow(this.parseValue, this.recordInlineListValue) | |
} | |
} | |
recordInlineListValue(value) { | |
if (!this.state.resultArr) { | |
this.state.resultArr = InlineList(tomlType(value)) | |
} | |
if (isFloat(value) || isInteger(value)) { | |
// unbox now that we've verified they're ok | |
this.state.resultArr.push(value.valueOf()) | |
} else { | |
this.state.resultArr.push(value) | |
} | |
return this.goto(this.parseInlineListNext) | |
} | |
parseInlineListNext() { | |
if (this.char === CHAR_SP || this.char === CTRL_I || this.char === CTRL_M || this.char === CTRL_J) { | |
return null | |
} else if (this.char === CHAR_NUM) { | |
return this.call(this.parseComment) | |
} else if (this.char === CHAR_COMMA) { | |
return this.next(this.parseInlineList) | |
} else if (this.char === CHAR_RSQB) { | |
return this.goto(this.parseInlineList) | |
} else { | |
throw this.error(new TomlError('Invalid character, expected whitespace, comma (,) or close bracket (])')) | |
} | |
} | |
/* INLINE TABLE */ | |
parseInlineTable() { | |
if (this.char === CHAR_SP || this.char === CTRL_I) { | |
return null | |
} else if (this.char === Parser.END || this.char === CHAR_NUM || this.char === CTRL_J || this.char === CTRL_M) { | |
throw this.error(new TomlError('Unterminated inline array')) | |
} else if (this.char === CHAR_RCUB) { | |
return this.return(this.state.resultTable || InlineTable()) | |
} else { | |
if (!this.state.resultTable) this.state.resultTable = InlineTable() | |
return this.callNow(this.parseAssign, this.recordInlineTableValue) | |
} | |
} | |
recordInlineTableValue(kv) { | |
let target = this.state.resultTable | |
let finalKey = kv.key.pop() | |
for (let kw of kv.key) { | |
if (hasKey(target, kw) && (!isTable(target[kw]) || target[kw][_declared])) { | |
throw this.error(new TomlError("Can't redefine existing key")) | |
} | |
target = target[kw] = target[kw] || Table() | |
} | |
if (hasKey(target, finalKey)) { | |
throw this.error(new TomlError("Can't redefine existing key")) | |
} | |
if (isInteger(kv.value) || isFloat(kv.value)) { | |
target[finalKey] = kv.value.valueOf() | |
} else { | |
target[finalKey] = kv.value | |
} | |
return this.goto(this.parseInlineTableNext) | |
} | |
parseInlineTableNext() { | |
if (this.char === CHAR_SP || this.char === CTRL_I) { | |
return null | |
} else if (this.char === Parser.END || this.char === CHAR_NUM || this.char === CTRL_J || this.char === CTRL_M) { | |
throw this.error(new TomlError('Unterminated inline array')) | |
} else if (this.char === CHAR_COMMA) { | |
return this.next(this.parseInlineTablePostComma) | |
} else if (this.char === CHAR_RCUB) { | |
return this.goto(this.parseInlineTable) | |
} else { | |
throw this.error(new TomlError('Invalid character, expected whitespace, comma (,) or close bracket (])')) | |
} | |
} | |
parseInlineTablePostComma() { | |
if (this.char === CHAR_SP || this.char === CTRL_I) { | |
return null | |
} else if (this.char === Parser.END || this.char === CHAR_NUM || this.char === CTRL_J || this.char === CTRL_M) { | |
throw this.error(new TomlError('Unterminated inline array')) | |
} else if (this.char === CHAR_COMMA) { | |
throw this.error(new TomlError('Empty elements in inline tables are not permitted')) | |
} else if (this.char === CHAR_RCUB) { | |
throw this.error(new TomlError('Trailing commas in inline tables are not permitted')) | |
} else { | |
return this.goto(this.parseInlineTable) | |
} | |
} | |
} | |
return TOMLParser | |
} | |
function prettyError(err, buf) { | |
/* istanbul ignore if */ | |
if (err.pos == null || err.line == null) return err | |
let msg = err.message | |
msg += ` at row ${err.line + 1}, col ${err.col + 1}, pos ${err.pos}:\n` | |
/* istanbul ignore else */ | |
if (buf && buf.split) { | |
const lines = buf.split(/\n/) | |
const lineNumWidth = String(Math.min(lines.length, err.line + 3)).length | |
let linePadding = ' ' | |
while (linePadding.length < lineNumWidth) linePadding += ' ' | |
for (let ii = Math.max(0, err.line - 1); ii < Math.min(lines.length, err.line + 2); ++ii) { | |
let lineNum = String(ii + 1) | |
if (lineNum.length < lineNumWidth) lineNum = ' ' + lineNum | |
if (err.line === ii) { | |
msg += lineNum + '> ' + lines[ii] + '\n' | |
msg += linePadding + ' ' | |
for (let hh = 0; hh < err.col; ++hh) { | |
msg += ' ' | |
} | |
msg += '^\n' | |
} else { | |
msg += lineNum + ': ' + lines[ii] + '\n' | |
} | |
} | |
} | |
err.message = msg + '\n' | |
return err | |
} | |
const TOMLParser = makeParserClass(Parser); | |
function parseString(str) { | |
str = str.toString('utf8') | |
const parser = new TOMLParser() | |
try { | |
parser.parse(str) | |
return parser.finish() | |
} catch (err) { | |
throw prettyError(err, str) | |
} | |
} | |
module.exports = parseString | |
}); | |
ace.define('ace/mode/toml_worker', [], function (require, exports, module) { | |
"use strict"; | |
var oop = require("../lib/oop"); | |
var Mirror = require("../worker/mirror").Mirror; | |
const parse = require("./toml/toml_parse"); | |
var TomlWorker = exports.TomlWorker = function (sender) { | |
Mirror.call(this, sender); | |
this.setTimeout(200); | |
}; | |
oop.inherits(TomlWorker, Mirror); | |
(function () { | |
this.onUpdate = function () { | |
var value = this.doc.getValue(); | |
var errors = []; | |
try { | |
if (value) { | |
parse(value); | |
} | |
} catch (e) { | |
var pos = this.doc.indexToPosition(e.pos - 1); | |
errors.push({ | |
row: pos.row, | |
column: pos.column, | |
text: e.message, | |
type: "error" | |
}); | |
} | |
this.sender.emit("annotate", errors); | |
}; | |
}).call(TomlWorker.prototype); | |
exports.TomlWorker = TomlWorker; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment