1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-19 21:27:59 +01:00

Hackier but more reliable literal() stuff.

This commit is contained in:
Kris Maglione
2014-06-18 12:24:55 -07:00
parent fdf188166d
commit cde8cd6763
15 changed files with 66 additions and 63 deletions

View File

@@ -215,18 +215,18 @@ var Abbreviations = Module("abbreviations", {
nonkeyword: /[ "']/ nonkeyword: /[ "']/
}; };
this._match = util.regexp(literal(/* this._match = util.regexp(literal(function () /*
(^ | \s | <nonkeyword>) (<keyword>+ )$ | // full-id (^ | \s | <nonkeyword>) (<keyword>+ )$ | // full-id
(^ | \s | <keyword> ) (<nonkeyword>+ <keyword>)$ | // end-id (^ | \s | <keyword> ) (<nonkeyword>+ <keyword>)$ | // end-id
(^ | \s ) (\S* <nonkeyword> )$ // non-id (^ | \s ) (\S* <nonkeyword> )$ // non-id
*/), "x", params); */$), "x", params);
this._check = util.regexp(literal(/* this._check = util.regexp(literal(function () /*
^ (?: ^ (?:
<keyword>+ | // full-id <keyword>+ | // full-id
<nonkeyword>+ <keyword> | // end-id <nonkeyword>+ <keyword> | // end-id
\S* <nonkeyword> // non-id \S* <nonkeyword> // non-id
) $ ) $
*/), "x", params); */$), "x", params);
}, },
get allHives() contexts.allGroups.abbrevs, get allHives() contexts.allGroups.abbrevs,

View File

@@ -54,9 +54,9 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
delete window.liberator; delete window.liberator;
// Prevents box ordering bugs after our stylesheet is removed. // Prevents box ordering bugs after our stylesheet is removed.
styles.system.add("cleanup-sheet", config.styleableChrome, literal(/* styles.system.add("cleanup-sheet", config.styleableChrome, literal(function () /*
#TabsToolbar tab { display: none; } #TabsToolbar tab { display: none; }
*/)); */$));
styles.unregisterSheet("resource://dactyl-skin/dactyl.css"); styles.unregisterSheet("resource://dactyl-skin/dactyl.css");
DOM('#TabsToolbar tab', document).style.display; DOM('#TabsToolbar tab', document).style.display;
}, },
@@ -1041,15 +1041,15 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
}, this); }, this);
}, },
stringToURLArray: deprecated("dactyl.parseURLs", "parseURLs"), stringToURLArray: deprecated("dactyl.parseURLs", "parseURLs"),
urlish: Class.Memoize(() => util.regexp(literal(/* urlish: Class.Memoize(() => util.regexp(literal(function () /*
^ ( ^ (
<domain>+ (:\d+)? (/ .*) | <domain>+ (:\d+)? (/ .*) |
<domain>+ (:\d+) | <domain>+ (:\d+) |
<domain>+ \. [a-z0-9]+ | <domain>+ \. [a-z0-9]+ |
localhost localhost
) $ ) $
*/), "ix", { */$), "ix", {
domain: util.regexp(String.replace(literal(/* domain: util.regexp(String.replace(literal(function () /*
[^ [^
U0000-U002c // U002d-U002e --. U0000-U002c // U002d-U002e --.
U002f // / U002f // /
@@ -1058,7 +1058,7 @@ var Dactyl = Module("dactyl", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), {
U005b-U0060 // U0061-U007a A-Z U005b-U0060 // U0061-U007a A-Z
U007b-U007f U007b-U007f
] ]
*/), /U/g, "\\u"), "x") */$), /U/g, "\\u"), "x")
})), })),
pluginFiles: {}, pluginFiles: {},

View File

@@ -38,20 +38,20 @@ var StatusLine = Module("statusline", {
config.tabbrowser.getStatusPanel().hidden = true; config.tabbrowser.getStatusPanel().hidden = true;
if (this.statusBar.localName == "toolbar") { if (this.statusBar.localName == "toolbar") {
styles.system.add("addon-bar", config.styleableChrome, literal(/* styles.system.add("addon-bar", config.styleableChrome, literal(function () /*
#status-bar, #dactyl-status-bar { margin-top: 0 !important; } #status-bar, #dactyl-status-bar { margin-top: 0 !important; }
#dactyl-status-bar { min-height: 0 !important; } #dactyl-status-bar { min-height: 0 !important; }
:-moz-any(#addon-bar, #dactyl-addon-bar) > statusbar { -moz-box-flex: 1 } :-moz-any(#addon-bar, #dactyl-addon-bar) > statusbar { -moz-box-flex: 1 }
:-moz-any(#addon-bar, #dactyl-addon-bar) > xul|toolbarspring { visibility: collapse; } :-moz-any(#addon-bar, #dactyl-addon-bar) > xul|toolbarspring { visibility: collapse; }
#addon-bar > #addonbar-closebutton { visibility: collapse; } #addon-bar > #addonbar-closebutton { visibility: collapse; }
*/)); */$));
overlay.overlayWindow(window, { overlay.overlayWindow(window, {
append: [ append: [
["statusbar", { id: this._statusLine.id, ordinal: "0" }]] ["statusbar", { id: this._statusLine.id, ordinal: "0" }]]
}); });
highlight.loadCSS(util.compileMacro(literal(/* highlight.loadCSS(util.compileMacro(literal(function () /*
!AddonBar;#addon-bar,#dactyl-addon-bar { !AddonBar;#addon-bar,#dactyl-addon-bar {
padding-left: 0 !important; padding-left: 0 !important;
padding-top: 0 !important; padding-top: 0 !important;
@@ -68,12 +68,12 @@ var StatusLine = Module("statusline", {
color: inherit !important; color: inherit !important;
} }
AddonButton:not(:hover) background: transparent; AddonButton:not(:hover) background: transparent;
*/))({ padding: config.OS.isMacOSX ? "padding-right: 10px !important;" : "" })); */$))({ padding: config.OS.isMacOSX ? "padding-right: 10px !important;" : "" }));
if (document.getElementById("appmenu-button")) if (document.getElementById("appmenu-button"))
highlight.loadCSS(literal(/* highlight.loadCSS(literal(function () /*
AppmenuButton min-width: 0 !important; padding: 0 .5em !important; AppmenuButton min-width: 0 !important; padding: 0 .5em !important;
*/)); */$));
} }
let _commandline = "if (window.dactyl) return dactyl.modules.commandline"; let _commandline = "if (window.dactyl) return dactyl.modules.commandline";

View File

@@ -36,9 +36,9 @@ var Tabs = Module("tabs", {
tabs.switchTo(event.originalTarget.getAttribute("identifier")); tabs.switchTo(event.originalTarget.getAttribute("identifier"));
}; };
this.tabBinding = styles.system.add("tab-binding", "chrome://browser/content/browser.xul", literal(/* this.tabBinding = styles.system.add("tab-binding", "chrome://browser/content/browser.xul", literal(function () /*
xul|tab { -moz-binding: url(chrome://dactyl/content/bindings.xml#tab) !important; } xul|tab { -moz-binding: url(chrome://dactyl/content/bindings.xml#tab) !important; }
*/).replace(/tab-./g, m => config.OS.isMacOSX ? "tab-mac" : m), */$).replace(/tab-./g, m => config.OS.isMacOSX ? "tab-mac" : m),
false, true); false, true);
this.timeout(function () { this.timeout(function () {

View File

@@ -40,7 +40,7 @@ fi
mungeliterals=$(cat <<'!' mungeliterals=$(cat <<'!'
local $/; local $/;
$_ = <>; $_ = <>;
s{(?<!function )\bliteral\(/\*(.*?)\*/\)}{ s{(?<!function )\bliteral\((?:function \(\) )?/\*(.*?)\*/\$?\)}{
my $s = $1; my $s = $1;
$s =~ s/[\\']/\\$&/g; $s =~ s/[\\']/\\$&/g;
$s =~ s/\n/\\n\\$&/g; $s =~ s/\n/\\n\\$&/g;

View File

@@ -230,7 +230,10 @@ this.lazyRequire("util", ["FailedAssertion", "util"]);
literal.files = {}; literal.files = {};
literal.locations = {}; literal.locations = {};
function literal(/* comment */) { function literal(comment) {
if (comment)
return /^function.*?\/\*([^]*)\*\/(?:\/\* use strict \*\/)\s*\S$/.exec(comment)[1];
let { caller } = Components.stack; let { caller } = Components.stack;
while (caller && caller.language != 2) while (caller && caller.language != 2)
caller = caller.caller; caller = caller.caller;

View File

@@ -1239,14 +1239,14 @@ var Commands = Module("commands", {
} }
}, },
nameRegexp: util.regexp(literal(/* nameRegexp: util.regexp(literal(function () /*
[^ [^
0-9 0-9
<forbid> <forbid>
] ]
[^ <forbid> ]* [^ <forbid> ]*
*/), "gx", { */$), "gx", {
forbid: util.regexp(String.replace(literal(/* forbid: util.regexp(String.replace(literal(function () /*
U0000-U002c // U002d - U0000-U002c // U002d -
U002e-U002f U002e-U002f
U003a-U0040 // U0041-U005a a-z U003a-U0040 // U0041-U005a a-z
@@ -1269,12 +1269,12 @@ var Commands = Module("commands", {
Ufe70-Ufeff // Arabic Presentation Forms-B Ufe70-Ufeff // Arabic Presentation Forms-B
Uff00-Uffef // Halfwidth and Fullwidth Forms Uff00-Uffef // Halfwidth and Fullwidth Forms
Ufff0-Uffff // Specials Ufff0-Uffff // Specials
*/), /U/g, "\\u"), "x") */$), /U/g, "\\u"), "x")
}), }),
validName: Class.Memoize(function validName() util.regexp("^" + this.nameRegexp.source + "$")), validName: Class.Memoize(function validName() util.regexp("^" + this.nameRegexp.source + "$")),
commandRegexp: Class.Memoize(function commandRegexp() util.regexp(literal(/* commandRegexp: Class.Memoize(function commandRegexp() util.regexp(literal(function () /*
^ ^
(?P<spec> (?P<spec>
(?P<prespace> [:\s]*) (?P<prespace> [:\s]*)
@@ -1289,7 +1289,7 @@ var Commands = Module("commands", {
(?:. | \n)*? (?:. | \n)*?
)? )?
$ $
*/), "x", { */$), "x", {
name: this.nameRegexp name: this.nameRegexp
})), })),

View File

@@ -596,14 +596,14 @@ config.INIT = update(Object.create(config.INIT), config.INIT, {
let img = new window.Image; let img = new window.Image;
img.src = this.logo || "resource://dactyl-local-content/logo.png"; img.src = this.logo || "resource://dactyl-local-content/logo.png";
img.onload = util.wrapCallback(function () { img.onload = util.wrapCallback(function () {
highlight.loadCSS(literal(/* highlight.loadCSS(literal(function () /*
!Logo { !Logo {
display: inline-block; display: inline-block;
background: url({src}); background: url({src});
width: {width}px; width: {width}px;
height: {height}px; height: {height}px;
} }
*/).replace(/\{(.*?)\}/g, (m, m1) => img[m1])); */$).replace(/\{(.*?)\}/g, (m, m1) => img[m1]));
img = null; img = null;
}); });
}, },

View File

@@ -108,7 +108,7 @@ var Help = Module("Help", {
{ mimeType: "text/plain;charset=UTF-8" }) { mimeType: "text/plain;charset=UTF-8" })
.responseText; .responseText;
let re = util.regexp(UTF8(literal(/* let re = util.regexp(UTF8(literal(function () /*
^ (?P<comment> \s* # .*\n) ^ (?P<comment> \s* # .*\n)
| ^ (?P<space> \s*) | ^ (?P<space> \s*)
@@ -124,7 +124,7 @@ var Help = Module("Help", {
) )
| (?: ^ [^\S\n]* \n) + | (?: ^ [^\S\n]* \n) +
*/)), "gmxy"); */$)), "gmxy");
let betas = util.regexp(/\[((?:b|rc)\d)\]/, "gx"); let betas = util.regexp(/\[((?:b|rc)\d)\]/, "gx");

View File

@@ -229,14 +229,14 @@ var Highlights = Module("Highlight", {
return n1 + "[dactyl|highlight~=" + hl + "]"; return n1 + "[dactyl|highlight~=" + hl + "]";
}), }),
groupRegexp: util.regexp(literal(/* groupRegexp: util.regexp(literal(function () /*
^ ^
(\s* (?:\S|\s\S)+ \s+) (\s* (?:\S|\s\S)+ \s+)
\{ ([^}]*) \} \{ ([^}]*) \}
\s* \s*
$ $
*/), "gmx"), */$), "gmx"),
sheetRegexp: util.regexp(literal(/* sheetRegexp: util.regexp(literal(function () /*
^\s* ^\s*
!? \*? !? \*?
(?P<group> (?:[^;\s]|\s[^;\s])+ ) (?P<group> (?:[^;\s]|\s[^;\s])+ )
@@ -245,7 +245,7 @@ var Highlights = Module("Highlight", {
(?:; (?P<extends> (?:[^;\s]|\s[^;\s])+ )? )? (?:; (?P<extends> (?:[^;\s]|\s[^;\s])+ )? )?
\s* (?P<css> .*) \s* (?P<css> .*)
$ $
*/), "x"), */$), "x"),
// </css> // </css>
/** /**
@@ -328,7 +328,7 @@ var Highlights = Module("Highlight", {
commands.add(["hi[ghlight]"], commands.add(["hi[ghlight]"],
"Set the style of certain display elements", "Set the style of certain display elements",
function (args) { function (args) {
let style = literal(/* let style = literal(function () /*
; ;
display: inline-block !important; display: inline-block !important;
position: static !important; position: static !important;
@@ -336,7 +336,7 @@ var Highlights = Module("Highlight", {
width: 3em !important; min-width: 3em !important; max-width: 3em !important; width: 3em !important; min-width: 3em !important; max-width: 3em !important;
height: 1em !important; min-height: 1em !important; max-height: 1em !important; height: 1em !important; min-height: 1em !important; max-height: 1em !important;
overflow: hidden !important; overflow: hidden !important;
*/); */$);
let clear = args[0] == "clear"; let clear = args[0] == "clear";
if (clear) if (clear)
args.shift(); args.shift();

View File

@@ -680,13 +680,13 @@ var IO = Module("io", {
} }
rtItems.ftdetect.template = //{{{ rtItems.ftdetect.template = //{{{
literal(/*" Vim filetype detection file literal(function () /*" Vim filetype detection file
<header> <header>
au BufNewFile,BufRead *<name>rc*,*.<fileext> set filetype=<name> au BufNewFile,BufRead *<name>rc*,*.<fileext> set filetype=<name>
*/);//}}} */$);//}}}
rtItems.ftplugin.template = //{{{ rtItems.ftplugin.template = //{{{
literal(/*" Vim filetype plugin file literal(function () /*" Vim filetype plugin file
<header> <header>
if exists("b:did_ftplugin") if exists("b:did_ftplugin")
@@ -711,9 +711,9 @@ endif
let &cpo = s:cpo_save let &cpo = s:cpo_save
unlet s:cpo_save unlet s:cpo_save
*/);//}}} */$);//}}}
rtItems.syntax.template = //{{{ rtItems.syntax.template = //{{{
literal(/*" Vim syntax file literal(function () /*" Vim syntax file
<header> <header>
if exists("b:current_syntax") if exists("b:current_syntax")
@@ -792,7 +792,7 @@ let &cpo = s:cpo_save
unlet s:cpo_save unlet s:cpo_save
" vim: tw=130 et ts=8 sts=4 sw=4: " vim: tw=130 et ts=8 sts=4 sw=4:
*/);//}}} */$);//}}}
const { options } = modules; const { options } = modules;
@@ -1047,7 +1047,7 @@ unlet s:cpo_save
}; };
completion.addUrlCompleter("file", "Local files", function (context, full) { completion.addUrlCompleter("file", "Local files", function (context, full) {
let match = util.regexp(literal(/* let match = util.regexp(literal(function () /*
^ ^
(?P<prefix> (?P<prefix>
(?P<proto> (?P<proto>
@@ -1058,7 +1058,7 @@ unlet s:cpo_save
) )
(?P<path> \/[^\/]* )? (?P<path> \/[^\/]* )?
$ $
*/), "x").exec(context.filter); */$), "x").exec(context.filter);
if (match) { if (match) {
if (!match.path) { if (!match.path) {
context.key = match.proto; context.key = match.proto;

View File

@@ -190,7 +190,7 @@ function XMLChannel(uri, contentType, noErrorChannel, unprivileged) {
let type = this.channel.contentType; let type = this.channel.contentType;
if (/^text\/|[\/+]xml$/.test(type)) { if (/^text\/|[\/+]xml$/.test(type)) {
let stream = services.InputStream(channelStream); let stream = services.InputStream(channelStream);
let [, pre, doctype, url, extra, open, post] = util.regexp(literal(/* let [, pre, doctype, url, extra, open, post] = util.regexp(literal(function () /*
^ ([^]*?) ^ ([^]*?)
(?: (?:
(<!DOCTYPE \s+ \S+ \s+) (?:SYSTEM \s+ "([^"]*)" | ((?:[^[>\s]|\s[^[])*)) (<!DOCTYPE \s+ \S+ \s+) (?:SYSTEM \s+ "([^"]*)" | ((?:[^[>\s]|\s[^[])*))
@@ -198,7 +198,7 @@ function XMLChannel(uri, contentType, noErrorChannel, unprivileged) {
([^]*) ([^]*)
)? )?
$ $
*/), "x").exec(stream.read(4096)); */$), "x").exec(stream.read(4096));
this.writes.push(pre); this.writes.push(pre);
if (doctype) { if (doctype) {
this.writes.push(doctype + (extra || "") + " [\n"); this.writes.push(doctype + (extra || "") + " [\n");

View File

@@ -469,7 +469,7 @@ var Styles = Module("Styles", {
} }
}, },
propertyPattern: util.regexp(literal(/* propertyPattern: util.regexp(literal(function () /*
(?: (?:
(?P<preSpace> <space>*) (?P<preSpace> <space>*)
(?P<name> [-a-z]*) (?P<name> [-a-z]*)
@@ -491,14 +491,14 @@ var Styles = Module("Styles", {
)? )?
) )
(?P<postSpace> <space>* (?: ; | $) ) (?P<postSpace> <space>* (?: ; | $) )
*/), "gix", */$), "gix",
{ {
space: /(?: \s | \/\* .*? \*\/ )/, space: /(?: \s | \/\* .*? \*\/ )/,
string: /(?:" (?:[^\\"]|\\.)* (?:"|$) | '(?:[^\\']|\\.)* (?:'|$) )/ string: /(?:" (?:[^\\"]|\\.)* (?:"|$) | '(?:[^\\']|\\.)* (?:'|$) )/
}), }),
patterns: memoize({ patterns: memoize({
get property() util.regexp(literal(/* get property() util.regexp(literal(function () /*
(?: (?:
(?P<preSpace> <space>*) (?P<preSpace> <space>*)
(?P<name> [-a-z]*) (?P<name> [-a-z]*)
@@ -509,26 +509,26 @@ var Styles = Module("Styles", {
)? )?
) )
(?P<postSpace> <space>* (?: ; | $) ) (?P<postSpace> <space>* (?: ; | $) )
*/), "gix", this), */$), "gix", this),
get function() util.regexp(literal(/* get function() util.regexp(literal(function () /*
(?P<function> (?P<function>
\s* \( \s* \s* \( \s*
(?: <string> | [^)]* ) (?: <string> | [^)]* )
\s* (?: \) | $) \s* (?: \) | $)
) )
*/), "gx", this), */$), "gx", this),
space: /(?: \s | \/\* .*? \*\/ )/, space: /(?: \s | \/\* .*? \*\/ )/,
get string() util.regexp(literal(/* get string() util.regexp(literal(function () /*
(?P<string> (?P<string>
" (?:[^\\"]|\\.)* (?:"|$) | " (?:[^\\"]|\\.)* (?:"|$) |
' (?:[^\\']|\\.)* (?:'|$) ' (?:[^\\']|\\.)* (?:'|$)
) )
*/), "gx", this), */$), "gx", this),
get token() util.regexp(literal(/* get token() util.regexp(literal(function () /*
(?P<token> (?P<token>
(?P<word> [-\w]+) (?P<word> [-\w]+)
<function>? <function>?
@@ -538,7 +538,7 @@ var Styles = Module("Styles", {
| <space>+ | <space>+
| [^;}\s]+ | [^;}\s]+
) )
*/), "gix", this) */$), "gix", this)
}), }),
/** /**

View File

@@ -252,11 +252,11 @@ var Template = Module("Template", {
return [tag, { xmlns: "dactyl" }, topic]; return [tag, { xmlns: "dactyl" }, topic];
}, },
linkifyHelp: function linkifyHelp(str, help) { linkifyHelp: function linkifyHelp(str, help) {
let re = util.regexp(literal(/* let re = util.regexp(literal(function () /*
(?P<pre> [/\s]|^) (?P<pre> [/\s]|^)
(?P<tag> '[\w-]+' | :(?:[\w-]+!?|!) | (?:._)?<[\w-]+>\w* | \b[a-zA-Z]_(?:[\w[\]]+|.) | \[[\w-;]+\] | E\d{3} ) (?P<tag> '[\w-]+' | :(?:[\w-]+!?|!) | (?:._)?<[\w-]+>\w* | \b[a-zA-Z]_(?:[\w[\]]+|.) | \[[\w-;]+\] | E\d{3} )
(?= [[\)!,:;./\s]|$) (?= [[\)!,:;./\s]|$)
*/), "gx"); */$), "gx");
return this.highlightSubstrings(str, (function () { return this.highlightSubstrings(str, (function () {
for (let res in re.iterate(str)) for (let res in re.iterate(str))
yield [res.index + res.pre.length, res.tag.length]; yield [res.index + res.pre.length, res.tag.length];

View File

@@ -359,14 +359,14 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
let defaults = { lt: "<", gt: ">" }; let defaults = { lt: "<", gt: ">" };
let re = util.regexp(literal(/* let re = util.regexp(literal(function () /*
([^]*?) // 1 ([^]*?) // 1
(?: (?:
(<\{) | // 2 (<\{) | // 2
(< ((?:[a-z]-)?[a-z-]+?) (?:\[([0-9]+)\])? >) | // 3 4 5 (< ((?:[a-z]-)?[a-z-]+?) (?:\[([0-9]+)\])? >) | // 3 4 5
(\}>) // 6 (\}>) // 6
) )
*/), "gixy"); */$), "gixy");
macro = String(macro); macro = String(macro);
let end = 0; let end = 0;
for (let match in re.iterate(macro)) { for (let match in re.iterate(macro)) {
@@ -749,7 +749,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
* *
* @returns {XMLHttpRequest} * @returns {XMLHttpRequest}
*/ */
httpGet: function httpGet(url, params={}, self) { httpGet: function httpGet(url, params={}, self=null) {
if (callable(params)) if (callable(params))
// Deprecated. // Deprecated.
params = { callback: params.bind(self) }; params = { callback: params.bind(self) };
@@ -908,7 +908,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
}, },
// ripped from Firefox; modified // ripped from Firefox; modified
unsafeURI: Class.Memoize(() => util.regexp(String.replace(literal(/* unsafeURI: Class.Memoize(() => util.regexp(String.replace(literal(function () /*
[ [
\s \s
// Invisible characters (bug 452979) // Invisible characters (bug 452979)
@@ -922,7 +922,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
// Bidi formatting characters. (RFC 3987 sections 3.2 and 4.1 paragraph 6) // Bidi formatting characters. (RFC 3987 sections 3.2 and 4.1 paragraph 6)
U200E U200F U202A U202B U202C U202D U202E U200E U200F U202A U202B U202C U202D U202E
] ]
*/), /U/g, "\\u"), */$), /U/g, "\\u"),
"gx")), "gx")),
losslessDecodeURI: function losslessDecodeURI(url) { losslessDecodeURI: function losslessDecodeURI(url) {
return url.split("%25").map(function (url) { return url.split("%25").map(function (url) {