-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
//
// 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("styles", {
exports: ["Style", "Styles", "styles"],
- require: ["services", "util"],
- use: ["contexts", "messages", "template"]
-}, this);
+ require: ["services", "util"]
+});
+
+lazyRequire("contexts", ["Contexts"]);
+lazyRequire("template", ["template"]);
function cssUri(css) "chrome-data:text/css," + encodeURI(css);
-var namespace = "@namespace html " + XHTML.uri.quote() + ";\n" +
- "@namespace xul " + XUL.uri.quote() + ";\n" +
- "@namespace dactyl " + NS.uri.quote() + ";\n";
+var namespace = "@namespace html " + XHTML.quote() + ";\n" +
+ "@namespace xul " + XUL.quote() + ";\n" +
+ "@namespace dactyl " + NS.quote() + ";\n";
var Sheet = Struct("name", "id", "sites", "css", "hive", "agent");
Sheet.liveProperty = function (name) {
this[i] = val;
this.enabled = this.enabled;
});
-}
+};
Sheet.liveProperty("agent");
Sheet.liveProperty("css");
Sheet.liveProperty("sites");
update(Sheet.prototype, {
formatSites: function (uris)
template.map(this.sites,
- function (filter) <span highlight={uris.some(Styles.matchFilter(filter)) ? "Filter" : ""}>{filter}</span>,
- <>,</>),
+ function (filter) ["span", { highlight: uris.some(Styles.matchFilter(filter)) ? "Filter" : "" }, filter],
+ ","),
remove: function () { this.hive.remove(this); },
return preamble + css;
let selectors = filter.map(function (part)
- !/^(?:[a-z-]+[:*]|[a-z-.]+$)/i.test(part) ? "regexp(" + (".*(?:" + part + ").*").quote() + ")" :
+ !/^(?:[a-z-]+[:*]|[a-z-.]+$)/i.test(part) ? "regexp(" + Styles.quote(".*(?:" + part + ").*") + ")" :
(/[*]$/.test(part) ? "url-prefix" :
/[\/:]/.test(part) ? "url"
: "domain")
- + '("' + part.replace(/"/g, "%22").replace(/\*$/, "") + '")')
+ + '(' + Styles.quote(part.replace(/\*$/, "")) + ')')
.join(",\n ");
return preamble + "@-moz-document " + selectors + " {\n\n" + css + "\n\n}\n";
get modifiable() this.name !== "system",
addRef: function (obj) {
- this.refs.push(Cu.getWeakReference(obj));
+ this.refs.push(util.weakReference(obj));
this.dropRef(null);
},
dropRef: function (obj) {
* @param {number} index
*/
remove: function remove(name, filter, css, index) {
- let self = this;
if (arguments.length == 1) {
var matches = [name];
name = null;
if (filter && filter.indexOf(",") > -1)
return filter.split(",").reduce(
- function (n, f) n + self.removeSheet(name, f, index), 0);
+ (n, f) => n + this.removeSheet(name, f, index), 0);
if (filter == undefined)
filter = "";
this.cleanup();
this.allSheets = {};
- services["dactyl:"].providers["style"] = function styleProvider(uri) {
- let id = /^\/(\d*)/.exec(uri.path)[1];
- if (Set.has(styles.allSheets, id))
- return ["text/css", styles.allSheets[id].fullCSS];
- return null;
- };
+ update(services["dactyl:"].providers, {
+ "style": function styleProvider(uri, path) {
+ let id = parseInt(path);
+ if (Set.has(styles.allSheets, id))
+ return ["text/css", styles.allSheets[id].fullCSS];
+ return null;
+ }
+ });
},
cleanup: function cleanup() {
let uris = util.visibleURIs(content);
- let list = <table>
- <tr highlight="Title">
- <td/>
- <td/>
- <td style="padding-right: 1em;">{_("title.Name")}</td>
- <td style="padding-right: 1em;">{_("title.Filter")}</td>
- <td style="padding-right: 1em;">{_("title.CSS")}</td>
- </tr>
- <col style="min-width: 4em; padding-right: 1em;"/>
- <col style="min-width: 1em; text-align: center; color: red; font-weight: bold;"/>
- <col style="padding: 0 1em 0 1ex; vertical-align: top;"/>
- <col style="padding: 0 1em 0 0; vertical-align: top;"/>
- {
- template.map(hives, function (hive) let (i = 0)
- <tr style="height: .5ex;"/> +
- template.map(sheets(hive), function (sheet)
- <tr>
- <td highlight="Title">{!i++ ? hive.name : ""}</td>
- <td>{sheet.enabled ? "" : UTF8("×")}</td>
- <td>{sheet.name || hive.sheets.indexOf(sheet)}</td>
- <td>{sheet.formatSites(uris)}</td>
- <td>{sheet.css}</td>
- </tr>) +
- <tr style="height: .5ex;"/>)
- }
- </table>;
-
- // TODO: Move this to an ItemList to show this automatically
- if (list.*.length() === list.text().length() + 5)
- dactyl.echomsg(_("style.none"));
- else
- commandline.commandOutput(list);
+ let list = ["table", {},
+ ["tr", { highlight: "Title" },
+ ["td"],
+ ["td"],
+ ["td", { style: "padding-right: 1em;" }, _("title.Name")],
+ ["td", { style: "padding-right: 1em;" }, _("title.Filter")],
+ ["td", { style: "padding-right: 1em;" }, _("title.CSS")]],
+ ["col", { style: "min-width: 4em; padding-right: 1em;" }],
+ ["col", { style: "min-width: 1em; text-align: center; color: red; font-weight: bold;" }],
+ ["col", { style: "padding: 0 1em 0 1ex; vertical-align: top;" }],
+ ["col", { style: "padding: 0 1em 0 0; vertical-align: top;" }],
+ template.map(hives, function (hive) let (i = 0) [
+ ["tr", { style: "height: .5ex;" }],
+ template.map(sheets(hive), function (sheet)
+ ["tr", {},
+ ["td", { highlight: "Title" }, !i++ ? hive.name : ""],
+ ["td", {}, sheet.enabled ? "" : UTF8("×")],
+ ["td", {}, sheet.name || hive.sheets.indexOf(sheet)],
+ ["td", {}, sheet.formatSites(uris)],
+ ["td", {}, sheet.css]]),
+ ["tr", { style: "height: .5ex;" }]])];
+
+ // E4X-FIXME
+ // // TODO: Move this to an ItemList to show this automatically
+ // if (list.*.length() === list.text().length() + 5)
+ // dactyl.echomsg(_("style.none"));
+ // else
+ commandline.commandOutput(list);
},
registerSheet: function registerSheet(url, agent, reload) {
* @returns {nsIURI -> boolean}
*/
matchFilter: function (filter) {
+ filter = filter.trim();
+
if (filter === "*")
var test = function test(uri) true;
else if (!/^(?:[a-z-]+:|[a-z-.]+$)/.test(filter)) {
else
test = function test(uri) { try { return util.isSubdomain(uri.host, filter); } catch (e) { return false; } };
test.toString = function toString() filter;
+ test.key = filter;
if (arguments.length < 2)
return test;
return test(arguments[1]);
}
},
- propertyPattern: util.regexp(<![CDATA[
+ propertyPattern: util.regexp(literal(/*
(?:
(?P<preSpace> <space>*)
(?P<name> [-a-z]*)
)?
)
(?P<postSpace> <space>* (?: ; | $) )
- ]]>, "gix",
+ */), "gix",
{
space: /(?: \s | \/\* .*? \*\/ )/,
string: /(?:" (?:[^\\"]|\\.)* (?:"|$) | '(?:[^\\']|\\.)* (?:'|$) )/
}),
patterns: memoize({
- get property() util.regexp(<![CDATA[
+ get property() util.regexp(literal(/*
(?:
(?P<preSpace> <space>*)
(?P<name> [-a-z]*)
)?
)
(?P<postSpace> <space>* (?: ; | $) )
- ]]>, "gix", this),
+ */), "gix", this),
- get function() util.regexp(<![CDATA[
+ get function() util.regexp(literal(/*
(?P<function>
\s* \( \s*
(?: <string> | [^)]* )
\s* (?: \) | $)
)
- ]]>, "gx", this),
+ */), "gx", this),
space: /(?: \s | \/\* .*? \*\/ )/,
- get string() util.regexp(<![CDATA[
+ get string() util.regexp(literal(/*
(?P<string>
" (?:[^\\"]|\\.)* (?:"|$) |
' (?:[^\\']|\\.)* (?:'|$)
)
- ]]>, "gx", this),
+ */), "gx", this),
- get token() util.regexp(<![CDATA[
+ get token() util.regexp(literal(/*
(?P<token>
(?P<word> [-\w]+)
<function>?
| <space>+
| [^;}\s]+
)
- ]]>, "gix", this)
- })
+ */), "gix", this)
+ }),
+
+ /**
+ * Quotes a string for use in CSS stylesheets.
+ *
+ * @param {string} str
+ * @returns {string}
+ */
+ quote: function quote(str) {
+ return '"' + str.replace(/([\\"])/g, "\\$1").replace(/\n/g, "\\00000a") + '"';
+ },
}, {
- commands: function (dactyl, modules, window) {
+ commands: function initCommands(dactyl, modules, window) {
const { commands, contexts, styles } = modules;
function sheets(context, args, filter) {
context.compare = modules.CompletionContext.Sort.number;
context.generate = function () args["-group"].sheets;
context.keys.active = function (sheet) uris.some(sheet.closure.match);
- context.keys.description = function (sheet) <>{sheet.formatSites(uris)}: {sheet.css.replace("\n", "\\n")}</>
+ context.keys.description = function (sheet) [sheet.formatSites(uris), ": ", sheet.css.replace("\n", "\\n")];
if (filter)
context.filters.push(function ({ item }) filter(item));
Styles.splitContext(context);
command: "style",
arguments: [style.sites.join(",")],
literalArg: style.css,
- options: update(
- hive.name == "user" ? {} : { "-group": hive.name },
- style.name ? { "-name": style.name } : {})
+ options: {
+ "-group": hive.name == "user" ? undefined : hive.name,
+ "-name": style.name || undefined
+ }
})))
.flatten().array
});
});
});
},
- contexts: function (dactyl, modules, window) {
+ contexts: function initContexts(dactyl, modules, window) {
modules.contexts.Hives("styles",
Class("LocalHive", Contexts.Hive, {
init: function init(group) {
}
}));
},
- completion: function (dactyl, modules, window) {
- const names = Array.slice(util.computedStyle(window.document.createElement("div")));
+ completion: function initCompletion(dactyl, modules, window) {
+ const names = Array.slice(DOM(["div"], window.document).style);
modules.completion.css = function (context) {
context.title = ["CSS Property"];
context.keys = { text: function (p) p + ":", description: function () "" };
}
};
},
- javascript: function (dactyl, modules, window) {
- modules.JavaScript.setCompleter(["get", "add", "remove", "find"].map(function (m) styles.user[m]),
+ javascript: function initJavascript(dactyl, modules, window) {
+ modules.JavaScript.setCompleter(["get", "add", "remove", "find"].map(function (m) Hive.prototype[m]),
[ // Prototype: (name, filter, css, index)
function (context, obj, args) this.names,
function (context, obj, args) Styles.completeSite(context, window.content),
function (context, obj, args) this.sheets
]);
},
- template: function () {
+ template: function initTemplate() {
let patterns = Styles.patterns;
template.highlightCSS = function highlightCSS(css) {
- XML.prettyPrinting = XML.ignoreWhitespace = false;
-
- return this.highlightRegexp(css, patterns.property, function (match) <>{
- match.preSpace}{template.filter(match.name)}: {
+ return this.highlightRegexp(css, patterns.property, function (match) {
+ if (!match.length)
+ return [];
+ return ["", match.preSpace, template.filter(match.name), ": ",
template.highlightRegexp(match.value, patterns.token, function (match) {
if (match.function)
- return <>{template.filter(match.word)}{
+ return ["", template.filter(match.word),
template.highlightRegexp(match.function, patterns.string,
- function (match) <span highlight="String">{match.string}</span>)
- }</>;
+ function (match) ["span", { highlight: "String" }, match.string])
+ ];
if (match.important == "!important")
- return <span highlight="String">{match.important}</span>;
+ return ["span", { highlight: "String" }, match.important];
if (match.string)
- return <span highlight="String">{match.string}</span>;
- return template.highlightRegexp(match.wholeMatch, /^(\d+)(em|ex|px|in|cm|mm|pt|pc)?/g,
- function (m, n, u) <><span highlight="Number">{n}</span><span highlight="Object">{u || ""}</span></>);
- })
-
- }{ match.postSpace }</>
- )
- }
- },
+ return ["span", { highlight: "String" }, match.string];
+ return template._highlightRegexp(match.wholeMatch, /^(\d+)(em|ex|px|in|cm|mm|pt|pc)?/g,
+ function (m, n, u) [
+ ["span", { highlight: "Number" }, n],
+ ["span", { highlight: "Object" }, u || ""]
+ ]);
+ }),
+ match.postSpace
+ ];
+ });
+ };
+ }
});
endModule();
// catch(e){dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack);}
-// vim: set fdm=marker sw=4 ts=4 et ft=javascript:
+// vim: set fdm=marker sw=4 sts=4 ts=8 et ft=javascript: