diff --git a/common/Makefile.common b/common/Makefile similarity index 81% rename from common/Makefile.common rename to common/Makefile index e2a8dab6..e3d9e534 100644 --- a/common/Makefile.common +++ b/common/Makefile @@ -6,10 +6,10 @@ BUILD_DATE = $(shell date "+%Y/%m/%d %H:%M:%S") BASE = $(TOP)/../common LOCALEDIR = locale -DOC_SRC_FILES = $(wildcard $(LOCALEDIR)/*/*.txt) -LOCALES = $(shell ls $(LOCALEDIR)) +DOC_FILES = $(wildcard $(LOCALEDIR)/*/*.xml) -MAKE_JAR = VERSION="$(VERSION)" DATE="$(BUILD_DATE)" sh $(BASE)/make_jar.sh +export VERSION BUILD_DATE +MAKE_JAR = sh $(BASE)/make_jar.sh # TODO: specify source files manually? JAR_BASES = $(TOP) $(BASE) @@ -34,14 +34,13 @@ RDF_IN = $(RDF).in BUILD_DIR = build.$(VERSION).$(OS) -ASCIIDOC = asciidoc AWK = awk .SILENT: #### rules -TARGETS = all help info doc jar xpi install clean distclean $(JAR) +TARGETS = all help info jar xpi install clean distclean $(JAR) $(TARGETS:%=\%.%): echo MAKE $* $(@:$*.%=%) $(MAKE) -C $* $(@:$*.%=%) @@ -54,7 +53,6 @@ help: @echo @echo " make help - display this help" @echo " make info - show some info about the system" - @echo " make doc - build doc files" @echo " make jar - build a JAR ($(JAR))" @echo " make xpi - build an XPI ($(XPI_NAME))" @echo " make release - updates update.rdf (this is not for you)" @@ -66,7 +64,7 @@ help: info: @echo "version $(VERSION)" @echo "release file $(XPI)" - @echo "doc files $(DOC_SRC_FILES)" + @echo "doc files $(DOC_FILES)" @echo "xpi files $(XPI_FILES)" xpi: $(XPI) @@ -81,11 +79,11 @@ $(RDF): $(RDF_IN) Makefile < $< > $@ @echo "SUCCESS: $@" -clean: $(LOCALEDIR)/$(LOCALES:%=%.clean) +clean: @echo "General $(NAME) cleanup..." rm -f $(JAR) $(XPI) -distclean: $(LOCALEDIR)/$(LOCALES:%=%.distclean) clean +distclean: @echo "More $(NAME) cleanup..." rm -rf $(BUILD_DIR) @@ -100,12 +98,8 @@ $(XPI): $(JAR) #### jar -$(JAR): doc +$(JAR): @echo "Building JAR..." $(MAKE_JAR) "$(JAR)" "$(JAR_BASES)" "$(JAR_DIRS)" "$(JAR_TEXTS)" "$(JAR_BINS)" "$(JAR_FILES)" @echo "SUCCESS: $@" -#### doc (see Makefile.doc) - -doc: $(LOCALES:%=$(LOCALEDIR)/%.doc) ; - diff --git a/common/Makefile.doc b/common/Makefile.doc deleted file mode 100644 index 5d4cab1b..00000000 --- a/common/Makefile.doc +++ /dev/null @@ -1,68 +0,0 @@ -# Symlink me to (or include me from) locale/*/Makefile - -#### configuration - -ASCIIDOC = asciidoc -AWK = awk - -LOCALE = $(shell basename `pwd`) -DOCLANG = $(shell basename `pwd` | $(AWK) -F- '{ print ($$1 ~ /^[a-z][a-z]$$/) ? $$1 : "en" }') - -SRC_FILES = $(wildcard *.txt) -FILES = $(SRC_FILES:%.txt=%.html) -DEPS = $(wildcard lang-$(DOCLANG).conf) ${BASE}/asciidoc.conf $(BASE)/Makefile.doc - -DOC_FILES = $(FILES) version.html - -.SILENT: - -#### rules - -.PHONY: all help doc asciidoc check-asciidoc clean distclean -all: doc - -doc: asciidoc - -help: - @echo "$(NAME) $(VERSION) build" - @echo - @echo " make help - display this help" - @echo " make doc - build doc files" - @echo " make clean - clean up" - @echo " make distclean - clean up more" - -clean: - @echo "Cleanup of $(LOCALE) documentation..." - -distclean: clean - @echo "More cleanup of $(LOCALE) documentation..." - rm -f $(DOC_FILES) - -#### Makes single-file makes easier to type - -%: %.html %.txt ; - -#### asciidoc - -asciidoc: check-asciidoc $(DOC_FILES) - -check-asciidoc: - @$(ASCIIDOC) --version | $(AWK) '{ exit $$2 !~ /^8\.4\./ }' || \ - echo >&2 "Warning: asciidoc versions other than 8.4.x are unsupported" - -all.html: $(SRC_FILES) - -version.html: ../../NEWS $(DEPS) - @echo "DOC locale/$(LOCALE)/$@" - # NOTE: asciidoc doesn't source the conf file implicitly when processing stdin - sed -e '1i\ -heading::Version{nbsp}information[version-information]' \ - -e '/^[0-9]/d' \ - -e '/^ \+\* version /s/.*version \+\([0-9.]\+\).*/section::Version{nbsp}\1[version-\1]\ -/' ../../NEWS | \ - ${ASCIIDOC} -f $(BASE)/asciidoc.conf -a doctitle=version.html -o version.html - - -$(FILES): %.html: %.txt $(DEPS) - @echo "DOC locale/$(LOCALE)/$@" - $(ASCIIDOC) -f $(BASE)/asciidoc.conf -a configname=$(NAME) --unsafe -a linkcss -a quirks! -a lang=$(DOCLANG) -a doctitle="$$(basename $@)" -o $@ $< - diff --git a/vimperator/components/about-handler.js b/common/components/about-handler.js similarity index 100% rename from vimperator/components/about-handler.js rename to common/components/about-handler.js diff --git a/vimperator/components/commandline-handler.js b/common/components/commandline-handler.js similarity index 100% rename from vimperator/components/commandline-handler.js rename to common/components/commandline-handler.js diff --git a/common/components/protocols.js b/common/components/protocols.js new file mode 100644 index 00000000..7a7a0090 --- /dev/null +++ b/common/components/protocols.js @@ -0,0 +1,172 @@ +// Copyright (c) 2008-2009 Kris Maglione +// +// This work is licensed for reuse under an MIT license. Details are +// given in the LICENSE.txt file included with this file. + + +/* Adds support for data: URIs with chrome privileges + * and fragment identifiers. + * + * "chrome-data:" [; ]* "," [] + * + * By Kris Maglione, ideas from Ed Anuff's nsChromeExtensionHandler. + */ + +const Ci = Components.interfaces, Cc = Components.classes; + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + +const NS_BINDING_ABORTED = 0x804b0002; +const nsIProtocolHandler = Components.interfaces.nsIProtocolHandler; + +const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); + +let channel = Components.classesByID["{61ba33c0-3031-11d3-8cd0-0060b0fc14a3}"] + .getService(Ci.nsIProtocolHandler) + .newChannel(ioService.newURI("chrome://liberator/content/data", null, null)) + .QueryInterface(Ci.nsIRequest); +const systemPrincipal = channel.owner; +channel.cancel(NS_BINDING_ABORTED); +delete channel; + +function makeChannel(url, orig) +{ + let uri = ioService.newURI(url, null, null); + let channel = ioService.newChannelFromURI(uri); + channel.owner = systemPrincipal; + channel.originalURI = orig; + return channel; +} +function fakeChannel(orig) + makeChannel("chrome://liberator/content/does/not/exist", orig); +function redirect(to, orig) +{ + let html = .toXMLString(); + return makeChannel('data:text/html,' + escape(html), orig); +} + +function ChromeData() {} +ChromeData.prototype = { + contractID: "@mozilla.org/network/protocol;1?name=chrome-data", + classID: Components.ID("{c1b67a07-18f7-4e13-b361-2edcc35a5a0d}"), + classDescription: "Data URIs with chrome privileges", + QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIProtocolHandler]), + _xpcom_factory: { + createInstance: function (outer, iid) + { + if (!ChromeData.instance) + ChromeData.instance = new ChromeData(); + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return ChromeData.instance.QueryInterface(iid); + } + }, + + scheme: "chrome-data", + defaultPort: -1, + allowPort: function (port, scheme) false, + protocolFlags: nsIProtocolHandler.URI_NORELATIVE + | nsIProtocolHandler.URI_NOAUTH + | nsIProtocolHandler.URI_IS_UI_RESOURCE, + + newURI: function (spec, charset, baseURI) + { + var uri = Components.classes["@mozilla.org/network/standard-url;1"] + .createInstance(Components.interfaces.nsIStandardURL) + .QueryInterface(Components.interfaces.nsIURI); + uri.init(uri.URLTYPE_STANDARD, this.defaultPort, spec, charset, null); + return uri; + }, + + newChannel: function (uri) + { + try + { + if (uri.scheme == this.scheme) + return makeChannel(uri.spec.replace(/^.*?:\/*(.*)(?:#.*)?/, "data:$1"), uri); + } + catch (e) {} + return fakeChannel(); + } +}; + +function Liberator() +{ + this.wrappedJSObject = this; + + const self = this; + this.HELP_TAGS = {}; + this.FILE_MAP = {}; + this.OVERLAY_MAP = {}; + this.NAMESPACES = []; +} +Liberator.prototype = { + contractID: "@mozilla.org/network/protocol;1?name=liberator", + classID: Components.ID("{9c8f2530-51c8-4d41-b356-319e0b155c44}"), + classDescription: "Liberator utility protocol", + QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIProtocolHandler]), + _xpcom_factory: { + createInstance: function (outer, iid) + { + if (!Liberator.instance) + Liberator.instance = new Liberator(); + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + return Liberator.instance.QueryInterface(iid); + } + }, + + init: function (obj) + { + for each (let prop in ["HELP_TAGS", "FILE_MAP", "OVERLAY_MAP", "NAMESPACES"]) + for (let [k, v] in Iterator(obj[prop])) + this[prop][k] = v + }, + + scheme: "liberator", + defaultPort: -1, + allowPort: function (port, scheme) false, + protocolFlags: 0 + | nsIProtocolHandler.URI_IS_UI_RESOURCE + | nsIProtocolHandler.URI_IS_LOCAL_RESOURCE, + + newURI: function (spec, charset, baseURI) + { + var uri = Components.classes["@mozilla.org/network/standard-url;1"] + .createInstance(Components.interfaces.nsIStandardURL) + .QueryInterface(Components.interfaces.nsIURI); + uri.init(uri.URLTYPE_STANDARD, this.defaultPort, spec, charset, baseURI); + return uri; + }, + + newChannel: function (uri) + { + try + { + switch(uri.host) + { + case "help": + let url = this.FILE_MAP[uri.path.replace(/^\/|#.*/g, "")]; + return makeChannel(url, uri); + case "help-overlay": + url = this.OVERLAY_MAP[uri.path.replace(/^\/|#.*/g, "")]; + return makeChannel(url, uri); + case "help-tag": + let tag = uri.path.substr(1); + if (tag in this.HELP_TAGS) + return redirect("liberator://help/" + this.HELP_TAGS[tag] + "#" + tag, uri); + } + } + catch (e) {} + return fakeChannel(uri); + } +}; + +var components = [ChromeData, Liberator]; + +function NSGetModule(compMgr, fileSpec) +{ + return XPCOMUtils.generateModule(components); +} + +// vim: set fdm=marker sw=4 ts=4 et: diff --git a/common/content/bookmarks.js b/common/content/bookmarks.js index f076bee8..8b5f7574 100644 --- a/common/content/bookmarks.js +++ b/common/content/bookmarks.js @@ -77,14 +77,23 @@ function Bookmarks() //{{{ function loadBookmark(node) { - let uri = util.newURI(node.uri); - let keyword = bookmarksService.getKeywordForBookmark(node.itemId); - let tags = taggingService.getTagsForURI(uri, {}) || []; - let bmark = new Bookmark(node.uri, node.title, node.icon && node.icon.spec, keyword, tags, node.itemId); + try + { + let uri = util.newURI(node.uri); + let keyword = bookmarksService.getKeywordForBookmark(node.itemId); + let tags = taggingService.getTagsForURI(uri, {}) || []; + let bmark = new Bookmark(node.uri, node.title, node.icon && node.icon.spec, keyword, tags, node.itemId); - bookmarks.push(bmark); + bookmarks.push(bmark); - return bmark; + return bmark; + } + catch (e) + { + liberator.dump("Failed to create bookmark for URI: " + node.uri); + liberator.reportError(e); + return null; + } } function readBookmark(id) @@ -702,7 +711,6 @@ function Bookmarks() //{{{ // if the search also requires a postData, [url, postData] is returned getSearchURL: function getSearchURL(text, useDefsearch) { - let url = null; let searchString = (useDefsearch ? options["defsearch"] + " " : "") + text; // we need to make sure our custom alias have been set, even if the user @@ -872,10 +880,10 @@ function History() //{{{ let sh = history.session; context.anchored = false; - context.completions = sh.slice(0, sh.index).reverse(); - context.keys = { text: function (item) (sh.index - item.index) + ": " + item.URI.spec, description: "title", icon: "icon" }; context.compare = CompletionContext.Sort.unsorted; context.filters = [CompletionContext.Filter.textDescription]; + context.completions = sh.slice(0, sh.index).reverse(); + context.keys = { text: function (item) (sh.index - item.index) + ": " + item.URI.spec, description: "title", icon: "icon" }; }, count: true, literal: 0 @@ -914,10 +922,10 @@ function History() //{{{ let sh = history.session; context.anchored = false; - context.completions = sh.slice(sh.index + 1); - context.keys = { text: function (item) (item.index - sh.index) + ": " + item.URI.spec, description: "title", icon: "icon" }; context.compare = CompletionContext.Sort.unsorted; context.filters = [CompletionContext.Filter.textDescription]; + context.completions = sh.slice(sh.index + 1); + context.keys = { text: function (item) (item.index - sh.index) + ": " + item.URI.spec, description: "title", icon: "icon" }; }, count: true, literal: 0 diff --git a/common/content/buffer.js b/common/content/buffer.js index 6e57c834..537a2448 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -389,7 +389,7 @@ function Buffer() //{{{ let xpath = ["input[not(@type) or @type='text' or @type='password' or @type='file']", "textarea[not(@disabled) and not(@readonly)]"]; - let elements = [m for (m in buffer.evaluateXPath(xpath))].filter(function (match) { + let elements = [m for (m in util.evaluateXPath(xpath))].filter(function (match) { let computedStyle = util.computedStyle(match); return computedStyle.visibility != "hidden" && computedStyle.display != "none"; }); @@ -802,7 +802,7 @@ function Buffer() //{{{ } let nFeed = 0; - for (let link in buffer.evaluateXPath(["link[@href and (@rel='feed' or (@rel='alternate' and @type))]"], doc)) + for (let link in util.evaluateXPath(["link[@href and (@rel='feed' or (@rel='alternate' and @type))]"], doc)) { let rel = link.rel.toLowerCase(); let feed = { title: link.title, href: link.href, type: link.type || "" }; @@ -1012,48 +1012,6 @@ function Buffer() //{{{ */ addPageInfoSection: addPageInfoSection, - /** - * Evaluates an XPath expression in the current or provided - * document. It provides the xhtml, xhtml2 and liberator XML - * namespaces. The result may be used as an iterator. - * - * @param {string} expression The XPath expression to evaluate. - * @param {Document} doc The document to evaluate the expression in. - * @default The current document. - * @param {Node} elem The context element. - * @default doc - * @param {boolean} asIterator Whether to return the results as an - * XPath iterator. - */ - evaluateXPath: function (expression, doc, elem, asIterator) - { - if (!doc) - doc = window.content.document; - if (!elem) - elem = doc; - if (util.isArray(expression)) - expression = util.makeXPath(expression); - - let result = doc.evaluate(expression, elem, - function lookupNamespaceURI(prefix) - { - return { - xhtml: "http://www.w3.org/1999/xhtml", - xhtml2: "http://www.w3.org/2002/06/xhtml2", - liberator: NS.uri - }[prefix] || null; - }, - asIterator ? XPathResult.ORDERED_NODE_ITERATOR_TYPE : XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, - null - ); - - result.__iterator__ = asIterator - ? function () { let elem; while ((elem = this.iterateNext())) yield elem; } - : function () { for (let i = 0; i < this.snapshotLength; i++) yield this.snapshotItem(i); }; - - return result; - }, - /** * Returns the currently selected word. If the selection is * null, it tries to guess the word that the caret is @@ -1162,7 +1120,7 @@ function Buffer() //{{{ return true; } - let res = buffer.evaluateXPath(options.get("hinttags").defaultValue, frame.document); + let res = util.evaluateXPath(options.get("hinttags").defaultValue, frame.document); for (let [, regex] in Iterator(regexes)) { for (let i in util.range(res.snapshotLength, 0, -1)) diff --git a/common/content/commands.js b/common/content/commands.js index 3a736060..fdb92c75 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -1193,7 +1193,7 @@ function Commands() //{{{ let [, prefix, junk] = context.filter.match(/^(:*\d*)\w*(.?)/) || []; context.advance(prefix.length); if (!junk) - return context.fork("", 0, this, "command"); + return void context.fork("", 0, this, "command"); // dynamically get completions as specified with the command's completer function let command = commands.get(cmd); diff --git a/common/content/completion.js b/common/content/completion.js index 716f0a08..40f4d086 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -185,6 +185,7 @@ function CompletionContext(editor, name, offset) //{{{ this.getKey = function (item, key) (typeof self.keys[key] == "function") ? self.keys[key].call(this, item.item) : key in self.keys ? item.item[self.keys[key]] : item.item[key]; + return this; } CompletionContext.Sort = { @@ -233,7 +234,10 @@ CompletionContext.prototype = { if (!context.hasItems) return []; let prefix = self.value.substring(minStart, context.offset); - return context.items.map(function makeItem(item) ({ text: prefix + item.text, item: item.item })); + return context.items.map(function (item) ({ + text: prefix + item.text, + __proto__: item + })); }); return { start: minStart, items: util.Array.flatten(items), longestSubstring: this.longestAllSubstring }; } @@ -450,13 +454,13 @@ CompletionContext.prototype = { let filter = fixCase(this.filter); if (this.anchored) { - function compare(text, s) text.substr(0, s.length) == s; + var compare = function compare(text, s) text.substr(0, s.length) == s; substrings = util.map(util.range(filter.length, text.length + 1), function (end) text.substring(0, end)); } else { - function compare(text, s) text.indexOf(s) >= 0; + var compare = function compare(text, s) text.indexOf(s) >= 0; substrings = []; let start = 0; let idx; @@ -1153,12 +1157,12 @@ function Completion() //{{{ // Yes. If the [ starts at the beginning of a logical // statement, we're in an array literal, and we're done. if (get(-3, 0, STATEMENTS) == get(-2)[OFFSET]) - return; + return null; // Beginning of the statement upto the opening [ let obj = getObj(-3, get(-2)[OFFSET]); - return complete.call(this, obj, getKey(), null, string, last); + return void complete.call(this, obj, getKey(), null, string, last); } // Is this a function call? @@ -1208,7 +1212,7 @@ function Completion() //{{{ }; obj[0][1] += "." + func + "(... [" + args.length + "]"; - return complete.call(this, obj, key, compl, string, last); + return void complete.call(this, obj, key, compl, string, last); } // In a string that's not an obj key or a function arg. @@ -1243,7 +1247,7 @@ function Completion() //{{{ { // FIXME var o = top[OFFSET]; top[OFFSET] = offset; - return complete.call(this, obj, key); + return void complete.call(this, obj, key); } finally { diff --git a/common/content/configbase.js b/common/content/configbase.js index 41a5ada2..51a59608 100644 --- a/common/content/configbase.js +++ b/common/content/configbase.js @@ -50,13 +50,6 @@ const configbase = { //{{{ */ hostApplication: null, - /** - * @property {[string]} A list of HTML help files available under - * chrome://liberator/locale/. Used to generate help tag indexes for - * the :help command. - */ - helpFiles: [], - /** * @property {function} Called on liberator startup to allow for any * arbitrary application-specific initialization code. diff --git a/common/content/editor.js b/common/content/editor.js index 45c8bebf..fe0c26dc 100644 --- a/common/content/editor.js +++ b/common/content/editor.js @@ -178,10 +178,7 @@ function Editor() //{{{ { let matches = args.string.match(RegExp("^\\s*($|" + abbrevmatch + ")(?:\\s*$|\\s+(.*))")); if (!matches) - { - liberator.echoerr("E474: Invalid argument"); - return false; - } + return void liberator.echoerr("E474: Invalid argument"); let [, lhs, rhs] = matches; if (rhs) editor.addAbbreviation(mode, lhs, rhs); diff --git a/common/content/help.js b/common/content/help.js index 638e7037..a07745f8 100644 --- a/common/content/help.js +++ b/common/content/help.js @@ -1,17 +1,22 @@ -// Copyright (c) 2009 by Kris Maglione +// Copyright (c) 2009 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. -const win = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] - .getService(Ci.nsIWindowWatcher) - .activeWindow; -const liberator = win.liberator; +function checkFragment() +{ + document.title = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "title")[0].textContent; + var frag = document.location.hash.substr(1); + var elem = document.getElementById(frag); + if (elem) + window.content.scrollTo(0, window.content.scrollY + elem.getBoundingClientRect().top - 10); // 10px context +} -let page = liberator.findHelp(decodeURIComponent(document.location.search.substr(1))); -let url = page ? "chrome://liberator/locale/" + page : content.history.previous; - -win.getBrowser().loadURIWithFlags(url, Components.interfaces.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY, null, null, null); +document.addEventListener("load", checkFragment, true); +window.addEventListener("message", function (event) { + if (event.data == "fragmentChange") + checkFragment(); +}, true); // vim: set fdm=marker sw=4 ts=4 et: diff --git a/common/content/help.xsl b/common/content/help.xsl new file mode 100644 index 00000000..fbab61fc --- /dev/null +++ b/common/content/help.xsl @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Boolean + + + Number + + + String + + + + + + + + + + + + + + + # + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/common/content/help.xul b/common/content/help.xul deleted file mode 100644 index 16be6018..00000000 --- a/common/content/help.xul +++ /dev/null @@ -1,7 +0,0 @@ - - - -