]> git.donarmstrong.com Git - dactyl.git/blob - common/modules/config.jsm
9fb101a97746fb4a4b91d4bfdc318f215a6eba48
[dactyl.git] / common / modules / config.jsm
1 // Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
2 // Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
3 // Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
4 //
5 // This work is licensed for reuse under an MIT license. Details are
6 // given in the LICENSE.txt file included with this file.
7 "use strict";
8
9 try {
10
11 let global = this;
12 Components.utils.import("resource://dactyl/bootstrap.jsm");
13 defineModule("config", {
14     exports: ["ConfigBase", "Config", "config"],
15     require: ["services", "storage", "util", "template"],
16     use: ["io", "prefs"]
17 }, this);
18
19 var ConfigBase = Class("ConfigBase", {
20     /**
21      * Called on dactyl startup to allow for any arbitrary application-specific
22      * initialization code. Must call superclass's init function.
23      */
24     init: function init() {
25         this.features.push = deprecated("set.add", function push(feature) set.add(this, feature));
26         if (util.haveGecko("2b"))
27             set.add(this.features, "Gecko2");
28
29         this.timeout(function () {
30             services["dactyl:"].pages.dtd = function () [null,
31                 iter(config.dtdExtra,
32                      (["dactyl." + k, v] for ([k, v] in iter(config.dtd))),
33                      (["dactyl." + s, config[s]] for each (s in config.dtdStrings)))
34                   .map(function ([k, v]) ["<!ENTITY ", k, " '", String.replace(v || "null", /'/g, "&apos;"), "'>"].join(""))
35                   .join("\n")]
36         });
37     },
38
39     loadStyles: function loadStyles() {
40         const { highlight } = require("highlight");
41         highlight.styleableChrome = this.styleableChrome;
42         highlight.loadCSS(this.CSS);
43         highlight.loadCSS(this.helpCSS);
44         if (!util.haveGecko("2b"))
45             highlight.loadCSS(<![CDATA[
46                 !TabNumber               font-weight: bold; margin: 0px; padding-right: .8ex;
47                 !TabIconNumber {
48                     font-weight: bold;
49                     color: white;
50                     text-align: center;
51                     text-shadow: black -1px 0 1px, black 0 1px 1px, black 1px 0 1px, black 0 -1px 1px;
52                 }
53             ]]>);
54     },
55
56     get addonID() this.name + "@dactyl.googlecode.com",
57     addon: Class.memoize(function () {
58         let addon;
59         do {
60             addon = (JSMLoader.bootstrap || {}).addon;
61             if (addon && !addon.getResourceURI) {
62                 util.reportError(Error(_("addon.unavailable")));
63                 yield 10;
64             }
65         }
66         while (addon && !addon.getResourceURI);
67
68         if (!addon)
69             addon = require("addons").AddonManager.getAddonByID(this.addonID);
70         yield addon;
71     }, true),
72
73     /**
74      * The current application locale.
75      */
76     appLocale: Class.memoize(function () services.chromeRegistry.getSelectedLocale("global")),
77
78     /**
79      * The current dactyl locale.
80      */
81     locale: Class.memoize(function () this.bestLocale(this.locales)),
82
83     /**
84      * The current application locale.
85      */
86     locales: Class.memoize(function () {
87         // TODO: Merge with completion.file code.
88         function getDir(str) str.match(/^(?:.*[\/\\])?/)[0];
89
90         let uri = "resource://dactyl-locale/";
91         let jar = io.isJarURL(uri);
92         if (jar) {
93             let prefix = getDir(jar.JAREntry);
94             var res = iter(s.slice(prefix.length).replace(/\/.*/, "") for (s in io.listJar(jar.JARFile, prefix)))
95                         .toArray();
96         }
97         else {
98             res = array(f.leafName
99                         // Fails on FF3: for (f in util.getFile(uri).iterDirectory())
100                         for (f in values(util.getFile(uri).readDirectory()))
101                         if (f.isDirectory())).array;
102         }
103
104         function exists(pkg) {
105             try {
106                 services["resource:"].getSubstitution(pkg);
107                 return true;
108             }
109             catch (e) {
110                 return false;
111             }
112         }
113
114         return array.uniq([this.appLocale, this.appLocale.replace(/-.*/, "")]
115                             .filter(function (locale) exists("dactyl-locale-" + locale))
116                             .concat(res));
117     }),
118
119     /**
120      * Returns the best locale match to the current locale from a list
121      * of available locales.
122      *
123      * @param {[string]} list A list of available locales
124      * @returns {string}
125      */
126     bestLocale: function (list) {
127         let langs = set(list);
128         return values([this.appLocale, this.appLocale.replace(/-.*/, ""),
129                        "en", "en-US", iter(langs).next()])
130             .nth(function (l) set.has(langs, l), 0);
131     },
132
133     haveHg: Class.memoize(function () {
134         if (/pre$/.test(this.addon.version)) {
135             let uri = this.addon.getResourceURI("../.hg");
136             if (uri instanceof Ci.nsIFileURL &&
137                     uri.QueryInterface(Ci.nsIFileURL).file.exists() &&
138                     io.pathSearch("hg"))
139                 return ["hg", "-R", uri.file.parent.path];
140         }
141         return null;
142     }),
143
144     branch: Class.memoize(function () {
145         if (this.haveHg)
146             return io.system(this.haveHg.concat(["branch"])).output;
147         return (/pre-hg\d+-(\S*)/.exec(this.version) || [])[1];
148     }),
149
150     /** @property {string} The Dactyl version string. */
151     version: Class.memoize(function () {
152         if (/pre$/.test(this.addon.version)) {
153             let uri = this.addon.getResourceURI("../.hg");
154             if (uri instanceof Ci.nsIFileURL &&
155                     uri.QueryInterface(Ci.nsIFileURL).file.exists() &&
156                     io.pathSearch("hg")) {
157                 return io.system(["hg", "-R", uri.file.parent.path,
158                                   "log", "-r.",
159                                   "--template=hg{rev}-" + this.branch + " ({date|isodate})"]).output;
160             }
161         }
162         let version = this.addon.version;
163         if ("@DATE@" !== "@" + "DATE@")
164             version += " (created: @DATE@)";
165         return version;
166     }),
167
168     get fileExt() this.name.slice(0, -5),
169
170     dtd: memoize({
171         get name() config.name,
172         get home() "http://dactyl.sourceforge.net/",
173         get apphome() this.home + this.name,
174         code: "http://code.google.com/p/dactyl/",
175         get issues() this.home + "bug/" + this.name,
176         get plugins() "http://dactyl.sf.net/" + this.name + "/plugins",
177         get faq() this.home + this.name + "/faq",
178
179         "list.mailto": Class.memoize(function () config.name + "@googlegroups.com"),
180         "list.href": Class.memoize(function () "http://groups.google.com/group/" + config.name),
181
182         "hg.latest": Class.memoize(function () this.code + "source/browse/"), // XXX
183         "irc": "irc://irc.oftc.net/#pentadactyl",
184     }),
185
186     dtdExtra: {
187         "xmlns.dactyl": "http://vimperator.org/namespaces/liberator",
188         "xmlns.html":   "http://www.w3.org/1999/xhtml",
189         "xmlns.xul":    "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
190
191         "tag.command-line": '<link topic="command-line">command line</link>',
192         "tag.status-line":  '<link topic="status-line">status line</link>',
193     },
194
195     dtdStrings: [
196         "appName",
197         "fileExt",
198         "host",
199         "hostbin",
200         "idName",
201         "name",
202         "version"
203     ],
204
205     helpStyles: /^(Help|StatusLine|REPL)|^(Boolean|Indicator|MoreMsg|Number|Object|Logo|Key(word)?|String)$/,
206     styleHelp: function styleHelp() {
207         if (!this.helpStyled) {
208             const { highlight } = require("highlight");
209             for (let k in keys(highlight.loaded))
210                 if (this.helpStyles.test(k))
211                     highlight.loaded[k] = true;
212         }
213         this.helpCSS = true;
214     },
215
216     Local: function Local(dactyl, modules, window) ({
217         init: function init() {
218
219             let append = <e4x xmlns={XUL} xmlns:dactyl={NS}>
220                     <menupopup id="viewSidebarMenu"/>
221                     <broadcasterset id="mainBroadcasterSet"/>
222             </e4x>;
223             for each (let [id, [name, key, uri]] in Iterator(this.sidebars)) {
224                 append.XUL::menupopup[0].* +=
225                         <menuitem observes={"pentadactyl-" + id + "Sidebar"} label={name} accesskey={key} xmlns={XUL}/>
226                 append.XUL::broadcasterset[0].* +=
227                         <broadcaster id={"pentadactyl-" + id + "Sidebar"}
228                             autoCheck="false" type="checkbox" group="sidebar"
229                             sidebartitle={name} sidebarurl={uri}
230                             oncommand="toggleSidebar(this.id || this.observes);" xmlns={XUL}/>
231             }
232
233             util.overlayWindow(window, { append: append.elements() });
234         },
235
236         browser: Class.memoize(function () window.gBrowser),
237         tabbrowser: Class.memoize(function () window.gBrowser),
238
239         get browserModes() [modules.modes.NORMAL],
240
241         /**
242          * @property {string} The ID of the application's main XUL window.
243          */
244         mainWindowId: window.document.documentElement.id,
245
246         /**
247          * @property {number} The height (px) that is available to the output
248          *     window.
249          */
250         get outputHeight() this.browser.mPanelContainer.boxObject.height,
251
252         tabStrip: Class.memoize(function () window.document.getElementById("TabsToolbar") || this.tabbrowser.mTabContainer),
253     }),
254
255     /**
256      * @property {Object} A mapping of names and descriptions
257      *     of the autocommands available in this application. Primarily used
258      *     for completion results.
259      */
260     autocommands: {},
261
262     /**
263      * @property {Object} A map of :command-complete option values to completer
264      *     function names.
265      */
266     completers: {
267        abbreviation: "abbreviation",
268        altstyle: "alternateStyleSheet",
269        bookmark: "bookmark",
270        buffer: "buffer",
271        charset: "charset",
272        color: "colorScheme",
273        command: "command",
274        dialog: "dialog",
275        dir: "directory",
276        environment: "environment",
277        event: "autocmdEvent",
278        extension: "extension",
279        file: "file",
280        help: "help",
281        highlight: "highlightGroup",
282        history: "history",
283        javascript: "javascript",
284        macro: "macro",
285        mapping: "userMapping",
286        mark: "mark",
287        menu: "menuItem",
288        option: "option",
289        preference: "preference",
290        qmark: "quickmark",
291        runtime: "runtime",
292        search: "search",
293        shellcmd: "shellCommand",
294        toolbar: "toolbar",
295        url: "url",
296        usercommand: "userCommand"
297     },
298
299     /**
300      * @property {Object} Application specific defaults for option values. The
301      *     property names must be the options' canonical names, and the values
302      *     must be strings as entered via :set.
303      */
304     defaults: { guioptions: "rb" },
305     cleanups: {},
306
307     /**
308      * @property {Object} A map of dialogs available via the
309      *      :dialog command. Property names map dialog names to an array
310      *      as follows:
311      *  [0] description - A description of the dialog, used in
312      *                    command completion results for :dialog.
313      *  [1] action - The function executed by :dialog.
314      */
315     dialogs: {},
316
317     /**
318      * @property {set} A list of features available in this
319      *    application. Used extensively in feature test macros. Use
320      *    dactyl.has(feature) to check for a feature's presence
321      *    in this array.
322      */
323     features: {},
324
325     /**
326      * @property {string} The file extension used for command script files.
327      *     This is the name string sans "dactyl".
328      */
329     get fileExtension() this.name.slice(0, -6),
330
331     guioptions: {},
332
333     hasTabbrowser: false,
334
335     /**
336      * @property {string} The name of the application that hosts the
337      *     extension. E.g., "Firefox" or "XULRunner".
338      */
339     host: null,
340
341     /**
342      * @property {[[]]} An array of application specific mode specifications.
343      *     The values of each mode are passed to modes.addMode during
344      *     dactyl startup.
345      */
346     modes: [],
347
348     /**
349      * @property {string} The name of the extension.
350      *    Required.
351      */
352     name: null,
353
354     /**
355      * @property {[string]} A list of extra scripts in the dactyl or
356      *    application namespaces which should be loaded before dactyl
357      *    initialization.
358      */
359     scripts: [],
360
361     sidebars: {},
362
363     /**
364      * @property {string} The leaf name of any temp files created by
365      *     {@link io.createTempFile}.
366      */
367     get tempFile() this.name + ".tmp",
368
369     /**
370      * @constant
371      * @property {string} The default highlighting rules.
372      * See {@link Highlights#loadCSS} for details.
373      */
374     CSS: UTF8(String.replace(<><![CDATA[
375         // <css>
376         Boolean      color: red;
377         Function     color: navy;
378         Null         color: blue;
379         Number       color: blue;
380         Object       color: maroon;
381         String       color: green; white-space: pre;
382
383         Key          font-weight: bold;
384
385         Enabled      color: blue;
386         Disabled     color: red;
387
388         FontFixed                            font-family: monospace !important;
389         FontCode            font-size: 9pt;  font-family: -mox-fixed, monospace !important;
390         FontProportional    font-size: 10pt; font-family: "Droid Sans", "Helvetica LT Std", Helvetica, "DejaVu Sans", Verdana, sans-serif !important;
391
392         // Hack to give these groups slightly higher precedence
393         // than their unadorned variants.
394         CmdCmdLine;[dactyl|highlight]>*  &#x0d; StatusCmdLine;[dactyl|highlight]>*
395         CmdNormal;[dactyl|highlight]     &#x0d; StatusNormal;[dactyl|highlight]
396         CmdErrorMsg;[dactyl|highlight]   &#x0d; StatusErrorMsg;[dactyl|highlight]
397         CmdInfoMsg;[dactyl|highlight]    &#x0d; StatusInfoMsg;[dactyl|highlight]
398         CmdModeMsg;[dactyl|highlight]    &#x0d; StatusModeMsg;[dactyl|highlight]
399         CmdMoreMsg;[dactyl|highlight]    &#x0d; StatusMoreMsg;[dactyl|highlight]
400         CmdQuestion;[dactyl|highlight]   &#x0d; StatusQuestion;[dactyl|highlight]
401         CmdWarningMsg;[dactyl|highlight] &#x0d; StatusWarningMsg;[dactyl|highlight]
402
403         Normal            color: black   !important; background: white       !important; font-weight: normal !important;
404         StatusNormal      color: inherit !important; background: transparent !important;
405         ErrorMsg          color: white   !important; background: red         !important; font-weight: bold !important;
406         InfoMsg           color: black   !important; background: white       !important;
407         StatusInfoMsg     color: inherit !important; background: transparent !important;
408         LineNr            color: orange  !important; background: white       !important;
409         ModeMsg           color: black   !important; background: white       !important;
410         StatusModeMsg     color: inherit !important; background: transparent !important; padding-right: 1em;
411         MoreMsg           color: green   !important; background: white       !important;
412         StatusMoreMsg                                background: transparent !important;
413         Message           white-space: pre-wrap !important; min-width: 100%; width: 100%; padding-left: 4em; text-indent: -4em; display: block;
414         Message String    white-space: pre-wrap;
415         NonText           color: blue; background: transparent !important;
416         *Preview          color: gray;
417         Question          color: green   !important; background: white       !important; font-weight: bold !important;
418         StatusQuestion    color: green   !important; background: transparent !important;
419         WarningMsg        color: red     !important; background: white       !important;
420         StatusWarningMsg  color: red     !important; background: transparent !important;
421
422         CmdLine;>*;;FontFixed   padding: 1px !important;
423         CmdPrompt;.dactyl-commandline-prompt
424         CmdInput;.dactyl-commandline-command
425         CmdOutput         white-space: pre;
426
427
428         CompGroup
429         CompGroup:not(:first-of-type)  margin-top: .5em;
430         CompGroup:last-of-type         padding-bottom: 1.5ex;
431
432         CompTitle            color: magenta; background: white; font-weight: bold;
433         CompTitle>*          padding: 0 .5ex;
434         CompTitleSep         height: 1px; background: magenta; background: -moz-linear-gradient(60deg, magenta, white);
435
436         CompMsg              font-style: italic; margin-left: 16px;
437
438         CompItem
439         CompItem:nth-child(2n+1)    background: rgba(0, 0, 0, .04);
440         CompItem[selected]   background: yellow;
441         CompItem>*           padding: 0 .5ex;
442
443         CompIcon             width: 16px; min-width: 16px; display: inline-block; margin-right: .5ex;
444         CompIcon>img         max-width: 16px; max-height: 16px; vertical-align: middle;
445
446         CompResult           width: 36%; padding-right: 1%; overflow: hidden;
447         CompDesc             color: gray; width: 62%; padding-left: 1em;
448
449         CompLess             text-align: center; height: 0;    line-height: .5ex; padding-top: 1ex;
450         CompLess::after      content: "⌃";
451
452         CompMore             text-align: center; height: .5ex; line-height: .5ex; margin-bottom: -.5ex;
453         CompMore::after      content: "⌄";
454
455
456         EditorEditing;;*   background: #bbb !important; -moz-user-input: none !important; -moz-user-modify: read-only !important;
457         EditorError;;*     background: red !important;
458         EditorBlink1;;*    background: yellow !important;
459         EditorBlink2;;*
460
461         REPL                overflow: auto; max-height: 40em;
462         REPL-R;;;Question
463         REPL-E              white-space: pre-wrap;
464         REPL-P              white-space: pre-wrap; margin-bottom: 1em;
465
466         Usage               width: 100%;
467         UsageBody
468         UsageHead
469         UsageItem
470         UsageItem:nth-of-type(2n)    background: rgba(0, 0, 0, .04);
471
472         Indicator   color: blue; width: 1.5em; text-align: center;
473         Filter      font-weight: bold;
474
475         Keyword     color: red;
476         Tag         color: blue;
477
478         Link                        position: relative; padding-right: 2em;
479         Link:not(:hover)>LinkInfo   opacity: 0; left: 0; width: 1px; height: 1px; overflow: hidden;
480         LinkInfo                    {
481             color: black;
482             position: absolute;
483             left: 100%;
484             padding: 1ex;
485             margin: -1ex -1em;
486             background: rgba(255, 255, 255, .8);
487             border-radius: 1ex;
488         }
489
490         StatusLine;;;FontFixed  {
491             -moz-appearance: none !important;
492             font-weight: bold;
493             background: transparent !important;
494             border: 0px !important;
495             padding-right: 0px !important;
496             min-height: 18px !important;
497             text-shadow: none !important;
498         }
499         StatusLineNormal;[dactyl|highlight]    color: white !important; background: black   !important;
500         StatusLineBroken;[dactyl|highlight]    color: black !important; background: #FFa0a0 !important; /* light-red */
501         StatusLineSecure;[dactyl|highlight]    color: black !important; background: #a0a0FF !important; /* light-blue */
502         StatusLineExtended;[dactyl|highlight]  color: black !important; background: #a0FFa0 !important; /* light-green */
503
504         TabClose;.tab-close-button
505         TabIcon;.tab-icon       min-width: 16px;
506         TabText;.tab-text
507         TabNumber               font-weight: bold; margin: 0px; padding-right: .8ex; cursor: default;
508         TabIconNumber {
509             cursor: default;
510             width: 16px;
511             margin: 0 2px 0 -18px !important;
512             font-weight: bold;
513             color: white;
514             text-align: center;
515             text-shadow: black -1px 0 1px, black 0 1px 1px, black 1px 0 1px, black 0 -1px 1px;
516         }
517
518         Title       color: magenta; font-weight: bold;
519         URL         text-decoration: none; color: green; background: inherit;
520         URL:hover   text-decoration: underline; cursor: pointer;
521         URLExtra    color: gray;
522
523         FrameIndicator;;* {
524             background-color: red;
525             opacity: 0.5;
526             z-index: 999999;
527             position: fixed;
528             top:      0;
529             bottom:   0;
530             left:     0;
531             right:    0;
532         }
533
534         Bell          background-color: black !important;
535
536         Hint;;* {
537             font:        bold 10px "Droid Sans Mono", monospace !important;
538             margin:      -.2ex;
539             padding:     0 0 0 1px;
540             outline:     1px solid rgba(0, 0, 0, .5);
541             background:  rgba(255, 248, 231, .8);
542             color:       black;
543         }
544         Hint[active];;*  background: rgba(255, 253, 208, .8);
545         Hint::after;;*   content: attr(text) !important;
546         HintElem;;*      background-color: yellow  !important; color: black !important;
547         HintActive;;*    background-color: #88FF00 !important; color: black !important;
548         HintImage;;*     opacity: .5 !important;
549
550         Button                  display: inline-block; font-weight: bold; cursor: pointer; color: black; text-decoration: none;
551         Button:hover            text-decoration: underline;
552         Button[collapsed]       visibility: collapse; width: 0;
553         Button::before          content: "["; color: gray; text-decoration: none !important;
554         Button::after           content: "]"; color: gray; text-decoration: none !important;
555         Button:not([collapsed]) ~ Button:not([collapsed])::before  content: "/[";
556
557         Buttons
558
559         DownloadCell                    display: table-cell; padding: 0 1ex;
560
561         Downloads                       display: table; margin: 0; padding: 0;
562         DownloadHead;;;CompTitle        display: table-row;
563         DownloadHead>*;;;DownloadCell
564
565         Download                        display: table-row;
566         Download:not([active])          color: gray;
567
568         Download>*;;;DownloadCell
569         DownloadButtons
570         DownloadPercent
571         DownloadProgress
572         DownloadProgressHave
573         DownloadProgressTotal
574         DownloadSource
575         DownloadState
576         DownloadTime
577         DownloadTitle
578         DownloadTitle>Link>a         max-width: 48ex; overflow: hidden; display: inline-block;
579
580         AddonCell                    display: table-cell; padding: 0 1ex;
581
582         Addons                       display: table; margin: 0; padding: 0;
583         AddonHead;;;CompTitle        display: table-row;
584         AddonHead>*;;;AddonCell
585
586         Addon                        display: table-row;
587
588         Addon>*;;;AddonCell
589         AddonButtons
590         AddonDescription
591         AddonName                    max-width: 48ex; overflow: hidden;
592         AddonStatus
593         AddonVersion
594
595         // </css>
596     ]]></>, /&#x0d;/g, "\n")),
597
598     helpCSS: UTF8(<><![CDATA[
599         // <css>
600         InlineHelpLink                              font-size: inherit !important; font-family: inherit !important;
601
602         Help;;;FontProportional                     line-height: 1.4em;
603
604         HelpInclude                                 margin: 2em 0;
605
606         HelpArg;;;FontCode                          color: #6A97D4;
607         HelpOptionalArg;;;FontCode                  color: #6A97D4;
608
609         HelpBody                                    display: block; margin: 1em auto; max-width: 100ex; padding-bottom: 1em; margin-bottom: 4em; border-bottom-width: 1px;
610         HelpBorder;*;dactyl://help/*                border-color: silver; border-width: 0px; border-style: solid;
611         HelpCode;;;FontCode                         display: block; white-space: pre; margin-left: 2em;
612         HelpTT;html|tt;dactyl://help/*;FontCode
613
614         HelpDefault;;;FontCode                      display: inline-block; margin: -1px 1ex 0 0; white-space: pre; vertical-align: text-top;
615
616         HelpDescription                             display: block; clear: right;
617         HelpDescription[short]                      clear: none;
618         HelpEm;html|em;dactyl://help/*              font-weight: bold; font-style: normal;
619
620         HelpEx;;;FontCode                           display: inline-block; color: #527BBD;
621
622         HelpExample                                 display: block; margin: 1em 0;
623         HelpExample::before                         content: "Example: "; font-weight: bold;
624
625         HelpInfo                                    display: block; width: 20em; margin-left: auto;
626         HelpInfoLabel                               display: inline-block; width: 6em;  color: magenta; font-weight: bold; vertical-align: text-top;
627         HelpInfoValue                               display: inline-block; width: 14em; text-decoration: none;             vertical-align: text-top;
628
629         HelpItem                                    display: block; margin: 1em 1em 1em 10em; clear: both;
630
631         HelpKey;;;FontCode                          color: #102663;
632         HelpKeyword                                 font-weight: bold; color: navy;
633
634         HelpLink;html|a;dactyl://help/*             text-decoration: none !important;
635         HelpLink[href]:hover                        text-decoration: underline !important;
636         HelpLink[href^="mailto:"]::after            content: "✉"; padding-left: .2em;
637         HelpLink[rel=external] {
638             /* Thanks, Wikipedia */
639             background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAFVBMVEVmmcwzmcyZzP8AZswAZv////////9E6giVAAAAB3RSTlP///////8AGksDRgAAADhJREFUGFcly0ESAEAEA0Ei6/9P3sEcVB8kmrwFyni0bOeyyDpy9JTLEaOhQq7Ongf5FeMhHS/4AVnsAZubxDVmAAAAAElFTkSuQmCC) no-repeat scroll right center;
640             padding-right: 13px;
641         }
642
643
644         HelpTOC
645         HelpTOC>ol ol                               margin-left: -1em;
646
647         HelpOrderedList;ol;dactyl://help/*                          margin: 1em 0;
648         HelpOrderedList1;ol[level="1"],ol;dactyl://help/*           list-style: outside decimal; display: block;
649         HelpOrderedList2;ol[level="2"],ol ol;dactyl://help/*        list-style: outside upper-alpha;
650         HelpOrderedList3;ol[level="3"],ol ol ol;dactyl://help/*     list-style: outside lower-roman;
651         HelpOrderedList4;ol[level="4"],ol ol ol ol;dactyl://help/*  list-style: outside decimal;
652
653         HelpList;html|ul;dactyl://help/*      display: block; list-style-position: outside; margin: 1em 0;
654         HelpListItem;html|li;dactyl://help/*  display: list-item;
655
656
657         HelpNote                                    color: red; font-weight: bold;
658
659         HelpOpt;;;FontCode                          color: #106326;
660         HelpOptInfo;;;FontCode                      display: block; margin-bottom: 1ex; padding-left: 4em;
661
662         HelpParagraph;html|p;dactyl://help/*        display: block; margin: 1em 0em;
663         HelpParagraph:first-child                   margin-top: 0;
664         HelpParagraph:last-child                    margin-bottom: 0;
665         HelpSpec;;;FontCode                         display: block; margin-left: -10em; float: left; clear: left; color: #527BBD; margin-right: 1em;
666
667         HelpString;;;FontCode                       color: green; font-weight: normal;
668         HelpString::before                          content: '"';
669         HelpString::after                           content: '"';
670         HelpString[delim]::before                   content: attr(delim);
671         HelpString[delim]::after                    content: attr(delim);
672
673         HelpNews        position: relative;
674         HelpNewsOld     opacity: .7;
675         HelpNewsNew     font-style: italic;
676         HelpNewsTag     font-style: normal; position: absolute; left: 100%; padding-left: 1em; color: #527BBD; opacity: .6; white-space: pre;
677
678         HelpHead;html|h1,html|h2,html|h3,html|h4;dactyl://help/* {
679             font-weight: bold;
680             color: #527BBD;
681             clear: both;
682         }
683         HelpHead1;html|h1;dactyl://help/* {
684             margin: 2em 0 1em;
685             padding-bottom: .2ex;
686             border-bottom-width: 1px;
687             font-size: 2em;
688         }
689         HelpHead2;html|h2;dactyl://help/* {
690             margin: 2em 0 1em;
691             padding-bottom: .2ex;
692             border-bottom-width: 1px;
693             font-size: 1.2em;
694         }
695         HelpHead3;html|h3;dactyl://help/* {
696             margin: 1em 0;
697             padding-bottom: .2ex;
698             font-size: 1.1em;
699         }
700         HelpHead4;html|h4;dactyl://help/* {
701         }
702
703
704         HelpTab;html|dl;dactyl://help/* {
705             display: table;
706             width: 100%;
707             margin: 1em 0;
708             border-bottom-width: 1px;
709             border-top-width: 1px;
710             padding: .5ex 0;
711             table-layout: fixed;
712         }
713         HelpTabColumn;html|column;dactyl://help/*   display: table-column;
714         HelpTabColumn:first-child                   width: 25%;
715         HelpTabTitle;html|dt;dactyl://help/*;FontCode  display: table-cell; padding: .1ex 1ex; font-weight: bold;
716         HelpTabDescription;html|dd;dactyl://help/*  display: table-cell; padding: .3ex 1em; text-indent: -1em; border-width: 0px;
717         HelpTabDescription>*;;dactyl://help/*       text-indent: 0;
718         HelpTabRow;html|dl>html|tr;dactyl://help/*  display: table-row;
719
720         HelpTag;;;FontCode                          display: inline-block; color: #527BBD; margin-left: 1ex; font-weight: normal;
721         HelpTags                                    display: block; float: right; clear: right;
722         HelpTopic;;;FontCode                        color: #102663;
723         HelpType;;;FontCode                         margin-right: 2ex;
724
725         HelpWarning                                 color: red; font-weight: bold;
726
727         HelpXML;;;FontCode                          color: #C5F779; background-color: #444444; font-family: Terminus, Fixed, monospace;
728         HelpXMLBlock {                              white-space: pre; color: #C5F779; background-color: #444444;
729             border: 1px dashed #aaaaaa;
730             display: block;
731             margin-left: 2em;
732             font-family: Terminus, Fixed, monospace;
733         }
734         HelpXMLAttribute                            color: #C5F779;
735         HelpXMLAttribute::after                     color: #E5E5E5; content: "=";
736         HelpXMLComment                              color: #444444;
737         HelpXMLComment::before                      content: "<!--";
738         HelpXMLComment::after                       content: "-->";
739         HelpXMLProcessing                           color: #C5F779;
740         HelpXMLProcessing::before                   color: #444444; content: "<?";
741         HelpXMLProcessing::after                    color: #444444; content: "?>";
742         HelpXMLString                               color: #C5F779; white-space: pre;
743         HelpXMLString::before                       content: '"';
744         HelpXMLString::after                        content: '"';
745         HelpXMLNamespace                            color: #FFF796;
746         HelpXMLNamespace::after                     color: #777777; content: ":";
747         HelpXMLTagStart                             color: #FFF796; white-space: normal; display: inline-block; text-indent: -1.5em; padding-left: 1.5em;
748         HelpXMLTagEnd                               color: #71BEBE;
749         HelpXMLText                                 color: #E5E5E5;
750         // </css>
751     ]]></>)
752 }, {
753 });
754
755 JSMLoader.loadSubScript("resource://dactyl-local-content/config.js", this);
756
757 config.INIT = update(Object.create(config.INIT), config.INIT, {
758     init: function init(dactyl, modules, window) {
759         init.superapply(this, arguments);
760
761         let img = window.Image();
762         img.src = this.logo || "resource://dactyl-local-content/logo.png";
763         img.onload = util.wrapCallback(function () {
764             const { highlight } = require("highlight");
765             highlight.loadCSS(<>{"!Logo  {"}
766                      display:    inline-block;
767                      background: url({img.src});
768                      width:      {img.width}px;
769                      height:     {img.height}px;
770                  {"}"}</>);
771             img = null;
772         });
773     },
774
775     load: function load(dactyl, modules, window) {
776         load.superapply(this, arguments);
777
778         this.timeout(function () {
779             if (this.branch && this.branch !== "default" &&
780                     modules.yes_i_know_i_should_not_report_errors_in_these_branches_thanks.indexOf(this.branch) === -1)
781                 dactyl.warn(_("warn.notDefaultBranch", config.appName, this.branch));
782         }, 1000);
783     }
784 });
785
786 endModule();
787
788 } catch(e){ if (typeof e === "string") e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
789
790 // vim: set fdm=marker sw=4 sts=4 et ft=javascript: