mirror of
https://github.com/linuxserver/core.git
synced 2026-02-20 05:07:19 +08:00
313 lines
11 KiB
JavaScript
313 lines
11 KiB
JavaScript
define(function(require, exports, module) {
|
|
main.consumes = [
|
|
"Plugin", "remote", "watcher", "fs", "save", "dialog.error", "commands"
|
|
];
|
|
main.provides = ["HTMLDocument"];
|
|
return main;
|
|
|
|
function main(options, imports, register) {
|
|
var Plugin = imports.Plugin;
|
|
var remote = imports.remote;
|
|
var watcher = imports.watcher;
|
|
var save = imports.save;
|
|
var fs = imports.fs;
|
|
var commands = imports.commands;
|
|
var Range = require("ace/range").Range;
|
|
|
|
var errorDialog = imports["dialog.error"];
|
|
var HTMLInstrumentation
|
|
= require("../../c9.ide.language.html.diff/HTMLInstrumentation");
|
|
|
|
function HTMLDocument(path) {
|
|
var exists = remote.findDocument(path);
|
|
if (exists) return exists;
|
|
|
|
/***** Initialization *****/
|
|
|
|
var plugin = new Plugin("Ajax.org", main.consumes);
|
|
// var emit = plugin.getEmitter();
|
|
|
|
var transports = [];
|
|
var tab, doc, errors = {};
|
|
|
|
var loaded = false;
|
|
function load() {
|
|
if (loaded) return false;
|
|
loaded = true;
|
|
|
|
remote.register(plugin);
|
|
}
|
|
|
|
/***** Methods *****/
|
|
|
|
function addTransport(transport) {
|
|
if (transports.indexOf(transport) == -1) {
|
|
transports.push(transport);
|
|
|
|
transport.addOther(function() {
|
|
var idx = transports.indexOf(transport);
|
|
if (~idx) {
|
|
transports.splice(idx, 1);
|
|
|
|
if (transports.length === 0)
|
|
plugin.unload();
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
if (doc)
|
|
initDom(transport);
|
|
|
|
if (tab && tab.isActive())
|
|
updateHighlight(true);
|
|
|
|
// if (doc && doc.changed)
|
|
// update();
|
|
|
|
return plugin;
|
|
}
|
|
|
|
function initTab(t) {
|
|
if (!t) {
|
|
doc = null;
|
|
if (tab) {
|
|
fs.readFile(path, function(err, data) {
|
|
update(null, data);
|
|
});
|
|
}
|
|
tab = null;
|
|
return;
|
|
}
|
|
|
|
tab = t;
|
|
doc = tab.document;
|
|
|
|
// Listen for change in the document
|
|
var c9session = doc.getSession();
|
|
c9session.once("init", function(e) {
|
|
e.session.on("change", update);
|
|
e.session.selection.on("changeCursor", updateHighlight);
|
|
e.session.savedDom = null;
|
|
e.session.dom = null;
|
|
e.session.htmldocument = plugin;
|
|
plugin.addOther(function () {
|
|
e.session.off("change", update);
|
|
e.session.selection.off("changeCursor", updateHighlight);
|
|
e.session.savedDom = null;
|
|
e.session.dom = null;
|
|
e.session.htmldocument = null;
|
|
});
|
|
transports.forEach(function(transport) {
|
|
initDom(transport, doc);
|
|
});
|
|
});
|
|
|
|
tab.editor.ace.on("focus", function() { updateHighlight(true); }, plugin);
|
|
tab.on("activate", function() { updateHighlight(); }, plugin);
|
|
tab.on("deactivate", function() { updateHighlight(false); }, plugin);
|
|
|
|
// Listen for a tab close event
|
|
tab.on("close", function() { watcher.watch(path); });
|
|
|
|
// @Ruben is there a better way to listen for save event?
|
|
save.on("afterSave", function(e) {
|
|
if (e.document == doc) {
|
|
var session = doc.getSession().session;
|
|
if (session) {
|
|
if (!session.dom && !session.savedDom && errors.save) {
|
|
errors.save = false;
|
|
transports.forEach(function(transport) {
|
|
transport.reload();
|
|
});
|
|
}
|
|
session.savedDom = session.dom;
|
|
}
|
|
}
|
|
}, plugin);
|
|
}
|
|
|
|
function initDom(transport) {
|
|
if (!doc) return;
|
|
var session = doc.getSession().session;
|
|
if (!session) return;
|
|
var docState = HTMLInstrumentation.syncTagIds(session);
|
|
if (!session.dom && docState.errors) {
|
|
var editList = HTMLInstrumentation.getUnappliedEditList(session);
|
|
if (!reportErrors(session, editList)) {
|
|
errors.save = true;
|
|
var name = doc.tab.path && doc.tab.path.match(/(^|\/)([^\/]*)$/)[2] || "the document";
|
|
errorDialog.show("Please save " + name + " to start a new live editing session");
|
|
}
|
|
}
|
|
if (docState.errors) {
|
|
session.dom = null;
|
|
this.errors = docState.errors;
|
|
console.log(this.errors);
|
|
} else {
|
|
transport.initHTMLDocument(docState);
|
|
}
|
|
}
|
|
|
|
function updateHighlight(e) {
|
|
var query, tagId;
|
|
|
|
if (tab && e !== false) {
|
|
var session = doc.getSession().session;
|
|
if (!session || !session.dom) return;
|
|
|
|
var pos = {
|
|
row: session.selection.lead.row,
|
|
column: session.selection.lead.column
|
|
};
|
|
if (session.doc.getLine(pos.row)[pos.column] === "<")
|
|
pos.column++; // prefer element after cursor
|
|
|
|
tagId = HTMLInstrumentation._getTagIDAtDocumentPos(session, pos);
|
|
}
|
|
|
|
if (tagId) {
|
|
query = "[data-cloud9-id='" + tagId + "']";
|
|
} else {
|
|
query = false;
|
|
}
|
|
|
|
// Send the highlight command
|
|
transports.forEach(function(transport) {
|
|
transport.highlightCSSQuery(query, e === true);
|
|
});
|
|
}
|
|
|
|
function update(changes, value) {
|
|
if (!changes) return; //@todo allow only value to be set
|
|
|
|
// Calculate changes
|
|
var session = doc.getSession().session;
|
|
if (!session.dom) {
|
|
transports.forEach(function(transport) {
|
|
initDom(transport);
|
|
});
|
|
return;
|
|
}
|
|
|
|
var result = HTMLInstrumentation.getUnappliedEditList(session, changes);
|
|
|
|
if (result.edits && result.edits.length) {
|
|
transports.forEach(function(transport) {
|
|
transport.processDOMChanges(result.edits, path);
|
|
});
|
|
}
|
|
|
|
reportErrors(session, result);
|
|
}
|
|
|
|
function reportErrors(session, editList) {
|
|
if (!editList.edits && editList.errors && editList.errors.length) {
|
|
scheduleDisplayError("Unable to update preview: unmatched tags detected");
|
|
} else {
|
|
scheduleDisplayError(false);
|
|
}
|
|
|
|
errors.unmatchedTags = editList.errors;
|
|
|
|
if (session.domErrorMarker) {
|
|
session.removeMarker(session.domErrorMarker);
|
|
session.domErrorMarker = null;
|
|
}
|
|
if (errors.unmatchedTags && errors.unmatchedTags.length) {
|
|
var error = errors.unmatchedTags[0];
|
|
var range = Range.fromPoints(error.startPos, error.endPos);
|
|
if (range.isEmpty()) {
|
|
range.start.column--;
|
|
range.end.column++;
|
|
}
|
|
session.domErrorMarker = session.addMarker(range, "language_highlight_error", "text");
|
|
}
|
|
return editList.errors && editList.errors.length;
|
|
}
|
|
|
|
function scheduleDisplayError(msg) {
|
|
clearTimeout(errors.timer);
|
|
if (!msg && !errors.msg) return;
|
|
errors.timer = setTimeout(function() {
|
|
errors.msg = msg;
|
|
errorDialog.show(msg, 2000);
|
|
}, 800);
|
|
}
|
|
|
|
function scrollIntoView() {
|
|
updateHighlight();
|
|
transports.forEach(function(transport) {
|
|
transport.reveal();
|
|
});
|
|
}
|
|
|
|
/***** Lifecycle *****/
|
|
|
|
plugin.on("load", function() {
|
|
load();
|
|
});
|
|
plugin.on("enable", function() {
|
|
|
|
});
|
|
plugin.on("disable", function() {
|
|
|
|
});
|
|
plugin.on("unload", function() {
|
|
loaded = false;
|
|
});
|
|
|
|
/***** Register and define API *****/
|
|
|
|
/**
|
|
*
|
|
**/
|
|
plugin.freezePublicAPI({
|
|
/**
|
|
*
|
|
*/
|
|
get path() { return path; },
|
|
|
|
/**
|
|
*
|
|
*/
|
|
get tab() { return tab; },
|
|
|
|
/**
|
|
*
|
|
*/
|
|
set tab(tab) { initTab(tab); },
|
|
|
|
_events: [
|
|
/**
|
|
* @event draw
|
|
*/
|
|
"draw"
|
|
],
|
|
|
|
/**
|
|
*
|
|
*/
|
|
addTransport: addTransport,
|
|
|
|
/**
|
|
*
|
|
*/
|
|
update: update,
|
|
|
|
/**
|
|
*
|
|
*/
|
|
scrollIntoView: scrollIntoView
|
|
});
|
|
|
|
plugin.load(null, "htmldocument");
|
|
|
|
return plugin;
|
|
}
|
|
|
|
register(null, {
|
|
HTMLDocument: HTMLDocument
|
|
});
|
|
}
|
|
}); |