1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2026-02-14 17:45:45 +01:00

Because I can.

This commit is contained in:
Kris Maglione
2011-08-21 00:47:18 -04:00
parent cef61c8733
commit 1607affa58
19 changed files with 802 additions and 786 deletions

View File

@@ -133,7 +133,8 @@ function defineModule(name, params, module) {
module.NAME = name;
module.EXPORTED_SYMBOLS = params.exports || [];
defineModule.loadLog.push("defineModule " + name);
defineModule.loadLog.push("[Begin " + name + "]");
defineModule.prefix += " ";
for (let [, mod] in Iterator(params.require || []))
require(module, mod);
@@ -152,11 +153,13 @@ function defineModule(name, params, module) {
defineModule.loadLog = [];
Object.defineProperty(defineModule.loadLog, "push", {
value: function (val) {
val = defineModule.prefix + val;
if (true)
defineModule.dump(val + "\n");
this[this.length] = Date.now() + " " + val;
}
});
defineModule.prefix = "";
defineModule.dump = function dump_() {
let msg = Array.map(arguments, function (msg) {
if (loaded.util && typeof msg == "object")
@@ -185,7 +188,8 @@ defineModule.time = function time(major, minor, func, self) {
}
function endModule() {
defineModule.loadLog.push("endModule " + currentModule.NAME);
defineModule.prefix = defineModule.prefix.slice(0, -2);
defineModule.loadLog.push("(End " + currentModule.NAME + ")");
for (let [, mod] in Iterator(use[currentModule.NAME] || []))
require(mod, currentModule.NAME, "use");
@@ -202,7 +206,7 @@ function require(obj, name, from) {
let caller = Components.stack.caller;
if (!loaded[name])
defineModule.loadLog.push(" " + (from || "require") + ": loading " + name + " into " + (obj.NAME || caller.filename + ":" + caller.lineNumber));
defineModule.loadLog.push((from || "require") + ": loading " + name + " into " + (obj.NAME || caller.filename + ":" + caller.lineNumber));
JSMLoader.load(name + ".jsm", obj);
return obj;
@@ -220,11 +224,12 @@ defineModule("base", {
// sed -n 's/^(const|function) ([a-zA-Z0-9_]+).*/ "\2",/p' base.jsm | sort | fmt
exports: [
"ErrorBase", "Cc", "Ci", "Class", "Cr", "Cu", "Module", "JSMLoader", "Object", "Runnable",
"Set", "Struct", "StructBase", "Timer", "UTF8", "XPCOM", "XPCOMUtils", "XPCSafeJSObjectWrapper",
"array", "bind", "call", "callable", "ctypes", "curry", "debuggerProperties", "defineModule",
"deprecated", "endModule", "forEach", "isArray", "isGenerator", "isinstance", "isObject",
"isString", "isSubclass", "iter", "iterAll", "iterOwnProperties", "keys", "memoize", "octal",
"properties", "require", "set", "update", "values", "withCallerGlobal"
"Set", "Struct", "StructBase", "Timer", "UTF8", "XPCOM", "XPCOMShim", "XPCOMUtils",
"XPCSafeJSObjectWrapper", "array", "bind", "call", "callable", "ctypes", "curry",
"debuggerProperties", "defineModule", "deprecated", "endModule", "forEach", "isArray",
"isGenerator", "isinstance", "isObject", "isString", "isSubclass", "iter", "iterAll",
"iterOwnProperties", "keys", "memoize", "octal", "properties", "require", "set", "update",
"values", "withCallerGlobal"
],
use: ["config", "services", "util"]
}, this);
@@ -754,6 +759,10 @@ function Class() {
constructor: { value: Constructor },
});
self.instance = self;
if ("_metaInit_" in self && self._metaInit_)
self._metaInit_.apply(self, arguments);
var res = self.init.apply(self, arguments);
return res !== undefined ? res : self;
})]]>,
@@ -1022,7 +1031,7 @@ function XPCOM(interfaces, superClass) {
interfaces = Array.concat(interfaces);
let shim = interfaces.reduce(function (shim, iface) shim.QueryInterface(iface),
Cc["@dactyl.googlecode.com/base/xpc-interface-shim"].createInstance());
XPCOMShim());
let res = Class("XPCOM(" + interfaces + ")", superClass || Class, update(
iter.toObject([k, v === undefined || callable(v) ? function stub() null : v]
@@ -1031,6 +1040,18 @@ function XPCOM(interfaces, superClass) {
shim = interfaces = null;
return res;
}
function XPCOMShim() {
let ip = services.InterfacePointer({
QueryInterface: function (iid) {
if (iid.equals(Ci.nsISecurityCheckedComponent))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
getHelperForLanguage: function () null,
getInterfaces: function (count) { count.value = 0; }
});
return ip.data;
};
/**
* An abstract base class for classes that wish to inherit from Error.
@@ -1065,24 +1086,32 @@ var ErrorBase = Class("ErrorBase", Error, {
* @returns {Class}
*/
function Module(name, prototype) {
let init = callable(prototype) ? 4 : 3;
let proto = arguments[callable(prototype) ? 2 : 1];
try {
let init = callable(prototype) ? 4 : 3;
let proto = arguments[callable(prototype) ? 2 : 1];
proto._metaInit_ = function () {
delete module.prototype._metaInit_;
currentModule[name.toLowerCase()] = this;
};
proto._metaInit_ = function () {
delete module.prototype._metaInit_;
currentModule[name.toLowerCase()] = this;
};
const module = Class.apply(Class, Array.slice(arguments, 0, init));
let instance = module();
module.className = name.toLowerCase();
const module = Class.apply(Class, Array.slice(arguments, 0, init));
let instance = module();
module.className = name.toLowerCase();
instance.INIT = update(Object.create(Module.INIT),
arguments[init] || {});
instance.INIT = update(Object.create(Module.INIT),
arguments[init] || {});
currentModule[module.className] = instance;
defineModule.modules.push(instance);
return module;
currentModule[module.className] = instance;
defineModule.modules.push(instance);
return module;
}
catch (e) {
if (typeof e === "string")
e = Error(e);
dump(e.fileName + ":" + e.lineNumber + ": " + e + "\n" + (e.stack || Error().stack));
}
}
Module.INIT = {
init: function Module_INIT_init(dactyl, modules, window) {

View File

@@ -19,11 +19,11 @@ if (!JSMLoader && "@mozilla.org/fuel/application;1" in Components.classes)
.getService(Components.interfaces.extIApplication)
.storage.get("dactyl.JSMLoader", null);
if (JSMLoader && JSMLoader.bump === 5)
if (JSMLoader && JSMLoader.bump === 6)
JSMLoader.global = this;
else
JSMLoader = {
bump: 5,
bump: 6,
builtin: Cu.Sandbox(this),
@@ -167,6 +167,24 @@ else
}
},
Factory: function Factory(clas) ({
__proto__: clas.prototype,
createInstance: function (outer, iid) {
try {
if (outer != null)
throw Cr.NS_ERROR_NO_AGGREGATION;
if (!clas.instance)
clas.instance = new clas();
return clas.instance.QueryInterface(iid);
}
catch (e) {
Cu.reportError(e);
throw e;
}
}
}),
registerFactory: function registerFactory(factory) {
this.manager.registerFactory(factory.classID,
String(factory.classID),

View File

@@ -12,7 +12,7 @@ Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("commands", {
exports: ["ArgType", "Command", "Commands", "CommandOption", "Ex", "commands"],
require: ["contexts", "messages", "util"],
use: ["config", "options", "services", "template"]
use: ["config", "help", "options", "services", "template"]
}, this);
/**
@@ -1585,7 +1585,7 @@ var Commands = Module("commands", {
cmd.hive == commands.builtin ? "" : <span highlight="Object" style="padding-right: 1em;">{cmd.hive.name}</span>
]
})),
iterateIndex: function (args) let (tags = services["dactyl:"].HELP_TAGS)
iterateIndex: function (args) let (tags = help.tags)
this.iterate(args).filter(function (cmd) cmd.hive === commands.builtin || Set.has(tags, cmd.helpTag)),
format: {
headings: ["Command", "Group", "Description"],

View File

@@ -6,16 +6,34 @@
// given in the LICENSE.txt file included with this file.
"use strict";
try {
let global = this;
Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("config", {
exports: ["ConfigBase", "Config", "config"],
require: ["services", "storage", "util", "template"],
require: ["protocol", "services", "storage", "util", "template"],
use: ["io", "messages", "prefs", "styles"]
}, this);
function AboutHandler() {}
AboutHandler.prototype = {
get classDescription() "About " + config.appName + " Page",
classID: Components.ID("81495d80-89ee-4c36-a88d-ea7c4e5ac63f"),
get contractID() "@mozilla.org/network/protocol/about;1?what=" + config.name,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
newChannel: function (uri) {
let channel = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService)
.newChannel("dactyl://content/about.xul", null, null);
channel.originalURI = uri;
return channel;
},
getURIFlags: function (uri) Ci.nsIAboutModule.ALLOW_SCRIPT,
};
var ConfigBase = Class("ConfigBase", {
/**
* Called on dactyl startup to allow for any arbitrary application-specific
@@ -26,9 +44,19 @@ var ConfigBase = Class("ConfigBase", {
if (this.haveGecko("2b"))
Set.add(this.features, "Gecko2");
JSMLoader.registerFactory(JSMLoader.Factory(AboutHandler));
JSMLoader.registerFactory(JSMLoader.Factory(
Protocol("dactyl", "{9c8f2530-51c8-4d41-b356-319e0b155c44}",
"resource://dactyl-content/")));
this.timeout(function () {
services["dactyl:"].pages.dtd = function () [null, util.makeDTD(config.dtd)];
});
update(services["dactyl:"].providers, {
"locale": function (uri, path) LocaleChannel("dactyl-locale", config.locale, path, uri),
"locale-local": function (uri, path) LocaleChannel("dactyl-local-locale", config.locale, path, uri)
});
},
modules: {
@@ -41,12 +69,14 @@ var ConfigBase = Class("ConfigBase", {
"contexts",
"downloads",
"finder",
"help",
"highlight",
"javascript",
"messages",
"options",
"overlay",
"prefs",
"protocol",
"sanitizer",
"services",
"storage",
@@ -1065,6 +1095,6 @@ config.INIT = update(Object.create(config.INIT), config.INIT, {
endModule();
} catch(e){ if (typeof e === "string") e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
// catch(e){ if (typeof e === "string") e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
// vim: set fdm=marker sw=4 sts=4 et ft=javascript:

326
common/modules/help.jsm Normal file
View File

@@ -0,0 +1,326 @@
// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
"use strict";
Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("help", {
exports: ["help"],
require: ["protocol", "services", "util"],
use: ["config", "highlight", "messages", "template"]
}, this);
var Help = Module("Help", {
init: function init() {
this.initialized = false;
this.files = {};
this.overlays = {};
this.tags = {};
function Loop(fn)
function (uri, path) {
if (!help.initialized)
return RedirectChannel(uri.spec, uri, 1);
return fn.apply(this, arguments);
}
update(services["dactyl:"].providers, {
"help": Loop(function (uri, path) help.files[path]),
"help-overlay": Loop(function (uri, path) help.overlays[path]),
"help-tag": Loop(function (uri, path) {
let tag = decodeURIComponent(path);
if (tag in help.files)
return RedirectChannel("dactyl://help/" + tag, uri);
if (tag in help.tags)
return RedirectChannel("dactyl://help/" + help.tags[tag] + "#" + tag.replace(/#/g, encodeURIComponent), uri);
})
});
},
Local: function Local(dactyl, modules, window) ({
init: function init() {
dactyl.commands["dactyl.help"] = function (event) {
let elem = event.originalTarget;
help.help(elem.getAttribute("tag") || elem.textContent);
};
},
/**
* Returns the URL of the specified help *topic* if it exists.
*
* @param {string} topic The help topic to look up.
* @param {boolean} consolidated Whether to search the consolidated help page.
* @returns {string}
*/
findHelp: function (topic, consolidated) {
if (!consolidated && Set.has(help.files, topic))
return topic;
let items = modules.completion._runCompleter("help", topic, null, !!consolidated).items;
let partialMatch = null;
function format(item) item.description + "#" + encodeURIComponent(item.text);
for (let [i, item] in Iterator(items)) {
if (item.text == topic)
return format(item);
else if (!partialMatch && topic)
partialMatch = item;
}
if (partialMatch)
return format(partialMatch);
return null;
},
/**
* Opens the help page containing the specified *topic* if it exists.
*
* @param {string} topic The help topic to open.
* @param {boolean} consolidated Whether to use the consolidated help page.
*/
help: function (topic, consolidated) {
dactyl.initHelp();
if (!topic) {
let helpFile = consolidated ? "all" : modules.options["helpfile"];
if (Set.has(help.files, helpFile))
dactyl.open("dactyl://help/" + helpFile, { from: "help" });
else
dactyl.echomsg(_("help.noFile", helpFile.quote()));
return;
}
let page = this.findHelp(topic, consolidated);
dactyl.assert(page != null, _("help.noTopic", topic));
dactyl.open("dactyl://help/" + page, { from: "help" });
}
}),
// Find the tags in the document.
addTags: function addTags(file, doc) {
for (let elem in DOM.XPath("//@tag|//dactyl:tags/text()|//dactyl:tag/text()", doc))
for (let tag in values((elem.value || elem.textContent).split(/\s+/)))
this.tags[tag] = file;
},
namespaces: ["locale-local", "locale"],
// Find help and overlay files with the given name.
findHelpFile: function findHelpFile(file) {
let result = [];
for (let namespace in values(this.namespaces)) {
let url = ["dactyl://", namespace, "/", file, ".xml"].join("");
let res = util.httpGet(url);
if (res) {
if (res.responseXML.documentElement.localName == "document")
this.files[file] = url;
if (res.responseXML.documentElement.localName == "overlay")
this.overlays[file] = url;
result.push(res.responseXML);
}
}
return result;
},
initialize: function initialize(force) {
// Waits for the add-on to become available, if necessary.
config.addon;
config.version;
if (force || !this.initialized) {
this.files["versions"] = function () {
let NEWS = util.httpGet(config.addon.getResourceURI("NEWS").spec,
{ mimeType: "text/plain;charset=UTF-8" })
.responseText;
let re = util.regexp(<![CDATA[
^ (?P<comment> \s* # .*\n)
| ^ (?P<space> \s*)
(?P<char> [-*+]) \ //
(?P<content> .*\n
(?: \2\ \ .*\n | \s*\n)* )
| (?P<par>
(?: ^ [^\S\n]*
(?:[^-*+\s] | [-*+]\S)
.*\n
)+
)
| (?: ^ [^\S\n]* \n) +
]]>, "gmxy");
let betas = util.regexp(/\[(b\d)\]/, "gx");
let beta = array(betas.iterate(NEWS))
.map(function (m) m[1]).uniq().slice(-1)[0];
default xml namespace = NS;
function rec(text, level, li) {
XML.ignoreWhitespace = XML.prettyPrinting = false;
let res = <></>;
let list, space, i = 0;
for (let match in re.iterate(text)) {
if (match.comment)
continue;
else if (match.char) {
if (!list)
res += list = <ul/>;
let li = <li/>;
li.* += rec(match.content.replace(RegExp("^" + match.space, "gm"), ""), level + 1, li);
list.* += li;
}
else if (match.par) {
let [, par, tags] = /([^]*?)\s*((?:\[[^\]]+\])*)\n*$/.exec(match.par);
let t = tags;
tags = array(betas.iterate(tags)).map(function (m) m[1]);
let group = !tags.length ? "" :
!tags.some(function (t) t == beta) ? "HelpNewsOld" : "HelpNewsNew";
if (i === 0 && li) {
li.@highlight = group;
group = "";
}
list = null;
if (level == 0 && /^.*:\n$/.test(match.par)) {
let text = par.slice(0, -1);
res += <h2 tag={"news-" + text}>{template.linkifyHelp(text, true)}</h2>;
}
else {
let [, a, b] = /^(IMPORTANT:?)?([^]*)/.exec(par);
res += <p highlight={group + " HelpNews"}>{
!tags.length ? "" :
<hl key="HelpNewsTag">{tags.join(" ")}</hl>
}{
a ? <hl key="HelpWarning">{a}</hl> : ""
}{
template.linkifyHelp(b, true)
}</p>;
}
}
i++;
}
for each (let attr in res..@highlight) {
attr.parent().@NS::highlight = attr;
delete attr.parent().@highlight;
}
return res;
}
XML.ignoreWhitespace = XML.prettyPrinting = false;
let body = rec(NEWS, 0);
for each (let li in body..li) {
let list = li..li.(@NS::highlight == "HelpNewsOld");
if (list.length() && list.length() == li..li.(@NS::highlight != "").length()) {
for each (let li in list)
li.@NS::highlight = "";
li.@NS::highlight = "HelpNewsOld";
}
}
return ["application/xml",
'<?xml version="1.0"?>\n' +
'<?xml-stylesheet type="text/xsl" href="dactyl://content/help.xsl"?>\n' +
'<!DOCTYPE document SYSTEM "resource://dactyl-content/dactyl.dtd">\n' +
<document xmlns={NS} xmlns:dactyl={NS}
name="versions" title={config.appName + " Versions"}>
<h1 tag="versions news NEWS">{config.appName} Versions</h1>
<toc start="2"/>
{body}
</document>.toXMLString()
];
}
// Scrape the list of help files from all.xml
// Manually process main and overlay files, since XSLTProcessor and
// XMLHttpRequest don't allow access to chrome documents.
this.tags["all"] = this.tags["all.xml"] = "all";
let files = this.findHelpFile("all").map(function (doc)
[f.value for (f in DOM.XPath("//dactyl:include/@href", doc))]);
// Scrape the tags from the rest of the help files.
array.flatten(files).forEach(function (file) {
this.tags[file + ".xml"] = file;
this.findHelpFile(file).forEach(function (doc) {
this.addTags(file, doc);
}, this);
}, this);
this.tags["versions"] = this.tags["versions.xml"] = "versions";
this.addTags("versions", util.httpGet("dactyl://help/versions").responseXML);
help.initialized = true;
}
},
}, {
}, {
commands: function init_commands(dactyl, modules, window) {
const { commands, completion, help } = modules;
[
{
name: "h[elp]",
description: "Open the introductory help page"
}, {
name: "helpa[ll]",
description: "Open the single consolidated help page"
}
].forEach(function (command) {
let consolidated = command.name == "helpa[ll]";
commands.add([command.name],
command.description,
function (args) {
dactyl.assert(!args.bang, _("help.dontPanic"));
help.help(args.literalArg, consolidated);
}, {
argCount: "?",
bang: true,
completer: function (context) completion.help(context, consolidated),
literal: 0
});
});
},
completion: function init_completion(dactyl, modules, window) {
const { completion } = modules;
completion.help = function completion_help(context, consolidated) {
dactyl.initHelp();
context.title = ["Help"];
context.anchored = false;
context.completions = help.tags;
if (consolidated)
context.keys = { text: 0, description: function () "all" };
};
},
mappings: function init_mappings(dactyl, modules, window) {
const { help, mappings, modes } = modules;
mappings.add([modes.MAIN], ["<open-help>", "<F1>"],
"Open the introductory help page",
function () { help.help(); });
mappings.add([modes.MAIN], ["<open-single-help>", "<A-F1>"],
"Open the single, consolidated help page",
function () { modules.ex.helpall(); });
}
});
endModule();
// vim: set fdm=marker sw=4 ts=4 et:

View File

@@ -13,7 +13,7 @@ Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("io", {
exports: ["IO", "io"],
require: ["services"],
use: ["config", "messages", "storage", "styles", "template", "util"]
use: ["config", "help", "messages", "storage", "styles", "template", "util"]
}, this);
// TODO: why are we passing around strings rather than file objects?
@@ -174,7 +174,7 @@ var IO = Module("io", {
util.flushCache();
dactyl.loadScript(uri.spec, context);
dactyl.helpInitialized = false;
help.initialized = false;
}
catch (e) {
if (e.fileName)

View File

@@ -9,7 +9,7 @@ try {
Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("overlay", {
exports: ["ModuleBase", "overlay"],
require: ["config", "highlight", "io", "services", "util"]
require: ["config", "help", "highlight", "io", "services", "util"]
}, this);
/**
@@ -41,8 +41,6 @@ var Overlay = Module("Overlay", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReferen
util.addObserver(this);
this.overlays = {};
services["dactyl:"]; // Hack. Force module initialization.
config.loadStyles();
this.timeout(this.initialize);

228
common/modules/protocol.jsm Normal file
View File

@@ -0,0 +1,228 @@
// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
"use strict";
Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("protocol", {
exports: ["LocaleChannel", "Protocol", "RedirectChannel", "StringChannel", "XMLChannel"],
require: ["services", "util"]
}, this);
var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"].getService(Ci.nsIPrincipal);
var DNE = "resource://gre/does/not/exist";
var _DNE;
function Channel(url, orig, noFake) {
try {
if (url == null)
return noFake ? null : FakeChannel(orig);
if (url instanceof Ci.nsIChannel)
return url;
if (typeof url === "function")
return let ([type, data] = url(orig)) StringChannel(data, type, orig);
if (isArray(url))
return let ([type, data] = url) StringChannel(data, type, orig);
let uri = services.io.newURI(url, null, null);
return (new XMLChannel(uri, null, noFake)).channel;
}
catch (e) {
util.reportError(e);
throw e;
}
}
function FakeChannel(orig) {
let channel = services.io.newChannel(DNE, null, null);
channel.originalURI = orig;
return channel;
}
function RedirectChannel(to, orig, time) {
let html = <html><head><meta http-equiv="Refresh" content={(time || 0) + ";" + to}/></head></html>.toXMLString();
return StringChannel(html, "text/html", services.io.newURI(to, null, null));
}
function Protocol(scheme, classID, contentBase) {
function Protocol() {
ProtocolBase.call(this);
}
Protocol.prototype = {
__proto__: ProtocolBase.prototype,
classID: Components.ID(classID),
scheme: scheme,
contentBase: contentBase,
_xpcom_factory: JSMLoader.Factory(Protocol),
};
return Protocol;
}
function ProtocolBase() {
this.wrappedJSObject = this;
this.pages = {};
this.providers = {};
}
ProtocolBase.prototype = {
get contractID() "@mozilla.org/network/protocol;1?name=" + this.scheme,
get classDescription() this.scheme + " utility protocol",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler]),
defaultPort: -1,
allowPort: function (port, scheme) false,
protocolFlags: 0
| Ci.nsIProtocolHandler.URI_IS_UI_RESOURCE
| Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE,
newURI: function newURI(spec, charset, baseURI) {
var uri = Cc["@mozilla.org/network/standard-url;1"]
.createInstance(Ci.nsIStandardURL)
.QueryInterface(Ci.nsIURI);
if (baseURI && baseURI.host === "data")
baseURI = null;
uri.init(uri.URLTYPE_STANDARD, this.defaultPort, spec, charset, baseURI);
return uri;
},
newChannel: function newChannel(uri) {
try {
uri.QueryInterface(Ci.nsIURL);
if (uri.host in this.providers)
return Channel(this.providers[uri.host](uri, uri.filePath.substr(1)), uri);
let path = decodeURIComponent(uri.path.replace(/^\/|#.*/g, ""));
switch(uri.host) {
case "content":
return Channel(this.pages[path] || this.contentBase + path, uri);
case "data":
try {
var channel = services.io.newChannel(uri.path.replace(/^\/(.*)(?:#.*)?/, "data:$1"),
null, null);
}
catch (e) {
var error = e;
break;
}
channel.contentCharset = "UTF-8";
channel.owner = systemPrincipal;
channel.originalURI = uri;
return channel;
}
}
catch (e) {
util.reportError(e);
}
if (error)
throw error;
return FakeChannel(uri);
}
};
function LocaleChannel(pkg, locale, path, orig) {
for each (let locale in [locale, "en-US"])
for each (let sep in "-/") {
var channel = Channel(["resource:/", pkg + sep + locale, path].join("/"), orig, true);
if (channel)
return channel;
}
return FakeChannel(orig);
}
function StringChannel(data, contentType, uri) {
let channel = services.StreamChannel(uri);
channel.contentStream = services.CharsetConv("UTF-8").convertToInputStream(data);
if (contentType)
channel.contentType = contentType;
channel.contentCharset = "UTF-8";
channel.owner = systemPrincipal;
if (uri)
channel.originalURI = uri;
return channel;
}
function XMLChannel(uri, contentType, noFake) {
try {
var channel = services.io.newChannelFromURI(uri);
var channelStream = channel.open();
}
catch (e) {
this.channel = noFake ? null : FakeChannel(uri);
return;
}
this.uri = uri;
this.sourceChannel = services.io.newChannelFromURI(uri);
this.pipe = services.Pipe(true, true, 0, 0, null);
this.writes = [];
this.channel = services.StreamChannel(uri);
this.channel.contentStream = this.pipe.inputStream;
this.channel.contentType = contentType || channel.contentType;
this.channel.contentCharset = "UTF-8";
this.channel.owner = systemPrincipal;
let stream = services.InputStream(channelStream);
let [, pre, doctype, url, open, post] = util.regexp(<![CDATA[
^ ([^]*?)
(?:
(<!DOCTYPE \s+ \S+ \s+) SYSTEM \s+ "([^"]*)"
(\s+ \[)?
([^]*)
)?
$
]]>, "x").exec(stream.read(4096));
this.writes.push(pre);
if (doctype) {
this.writes.push(doctype + "[\n");
try {
this.writes.push(services.io.newChannel(url, null, null).open());
}
catch (e) {}
if (!open)
this.writes.push("\n]");
this.writes.push(post);
}
this.writes.push(channelStream);
this.writeNext();
}
XMLChannel.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRequestObserver]),
writeNext: function () {
try {
if (!this.writes.length)
this.pipe.outputStream.close();
else {
let stream = this.writes.shift();
if (isString(stream))
stream = services.StringStream(stream);
services.StreamCopier(stream, this.pipe.outputStream, null,
false, true, 4096, true, false)
.asyncCopy(this, null);
}
}
catch (e) {
util.reportError(e);
}
},
onStartRequest: function (request, context) {},
onStopRequest: function (request, context, statusCode) {
this.writeNext();
}
};
endModule();
// vim: set fdm=marker sw=4 ts=4 et:

View File

@@ -656,7 +656,7 @@ var Sanitizer = Module("sanitizer", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakRef
options.add(["cookies", "ck"],
"The default mode for newly added cookie permissions",
"stringlist", "session",
{ get values() iter(Sanitizer.COMMANDS) });
{ get values() Sanitizer.COMMANDS });
options.add(["cookieaccept", "ca"],
"When to accept cookies",

View File

@@ -75,6 +75,7 @@ var Services = Module("Services", {
this.addClass("Find", "@mozilla.org/embedcomp/rangefind;1", "nsIFind");
this.addClass("HtmlConverter","@mozilla.org/widget/htmlformatconverter;1", "nsIFormatConverter");
this.addClass("HtmlEncoder", "@mozilla.org/layout/htmlCopyEncoder;1", "nsIDocumentEncoder");
this.addClass("InterfacePointer", "@mozilla.org/supports-interface-pointer;1", "nsISupportsInterfacePointer", "data");
this.addClass("InputStream", "@mozilla.org/scriptableinputstream;1", "nsIScriptableInputStream", "init");
this.addClass("Persist", "@mozilla.org/embedding/browser/nsWebBrowserPersist;1", "nsIWebBrowserPersist");
this.addClass("Pipe", "@mozilla.org/pipe;1", "nsIPipe", "init");

View File

@@ -8,7 +8,7 @@ Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("template", {
exports: ["Binding", "Template", "template"],
require: ["util"],
use: ["messages", "services"]
use: ["help", "messages", "services"]
}, this);
default xml namespace = XHTML;
@@ -204,7 +204,7 @@ var Template = Module("Template", {
},
helpLink: function (token, text, type) {
if (!services["dactyl:"].initialized)
if (!help.initialized)
util.dactyl.initHelp();
let topic = token; // FIXME: Evil duplication!
@@ -213,7 +213,7 @@ var Template = Module("Template", {
else if (/^n_/.test(topic))
topic = topic.slice(2);
if (services["dactyl:"].initialized && !Set.has(services["dactyl:"].HELP_TAGS, topic))
if (help.initialized && !Set.has(help.tags, topic))
return <span highlight={type || ""}>{text || token}</span>;
XML.ignoreWhitespace = false; XML.prettyPrinting = false;
@@ -224,7 +224,7 @@ var Template = Module("Template", {
return <a highlight={"InlineHelpLink " + type} tag={topic} href={"dactyl://help-tag/" + topic} dactyl:command="dactyl.help" xmlns:dactyl={NS}>{text || topic}</a>;
},
HelpLink: function (token) {
if (!services["dactyl:"].initialized)
if (!help.initialized)
util.dactyl.initHelp();
let topic = token; // FIXME: Evil duplication!
@@ -233,7 +233,7 @@ var Template = Module("Template", {
else if (/^n_/.test(topic))
topic = topic.slice(2);
if (services["dactyl:"].initialized && !Set.has(services["dactyl:"].HELP_TAGS, topic))
if (help.initialized && !Set.has(help.tags, topic))
return <>{token}</>;
XML.ignoreWhitespace = false; XML.prettyPrinting = false;