Merge branch 'develop' into feature/metrics

This commit is contained in:
Mark Hammond 2011-02-14 16:58:31 +11:00
Родитель 2cf99032a5 1473d94307
Коммит ed6997f96a
402 изменённых файлов: 28487 добавлений и 5932 удалений

Просмотреть файл

@ -1,27 +1,17 @@
version := 0.1.8
ifeq ($(TOPSRCDIR),)
export TOPSRCDIR = $(shell pwd)
endif
srcdir=$(TOPSRCDIR)/extensions/firefox-share/src/
objdir=$(TOPSRCDIR)/extensions/firefox-share/dist/
stage_dir=$(objdir)/stage
xpi_dir=$(TOPSRCDIR)/web
web_dir=$(TOPSRCDIR)/web
static_dir=$(TOPSRCDIR)/web-static
xpi_dir=$(TOPSRCDIR)/web/dev
web_dir=$(TOPSRCDIR)/web/dev
static_dir=$(TOPSRCDIR)/web/$(version)
webbuild_dir=$(TOPSRCDIR)/tools/webbuild
requirejs_dir=$(webbuild_dir)/requirejs
version := 0.7.3
ifeq ($(release_build),)
xpi_type := dev
update_url :=
else
xpi_type := rel
update_url :=
endif
xpi_name := share-$(version)-$(xpi_type).xpi
xpi_name := ffshare.xpi
xpi_files := chrome.manifest chrome install.rdf defaults components modules
dep_files := Makefile $(shell find $(srcdir) -type f)
@ -71,10 +61,16 @@ web: $(static_dir)
$(static_dir):
rsync -av $(web_dir)/ $(static_dir)/
cd $(webbuild_dir) && $(requirejs_dir)/build/build.sh share.build.js
cd $(webbuild_dir) && $(requirejs_dir)/build/build.sh frontpage.build.js
cd $(webbuild_dir) && $(requirejs_dir)/build/build.sh settings.build.js
perl -i -pe "s:version='[^']+':version='$(version)':" $(TOPSRCDIR)/setup.py
find $(static_dir) -name \*.html | xargs perl -i -pe 's:/dev/:/$(version)/:go'
cd $(static_dir) && $(requirejs_dir)/build/build.sh build.js
cd $(static_dir)/settings && $(requirejs_dir)/build/build.sh build.js
cd $(static_dir)/share && $(requirejs_dir)/build/build.sh build.js
cd $(static_dir)/share/panel && $(requirejs_dir)/build/build.sh build.js
cd $(static_dir)/.. && ln -n -f -s $(version) current
clean:
rm -rf $(objdir)
rm -rf $(static_dir)

Просмотреть файл

@ -47,14 +47,14 @@ Run the web server. 'reload' is useful for development, the webserver restarts o
paster serve --reload development.ini
Then visit: http://127.0.0.1:5000/ for an index of api examples
Then visit: [http://127.0.0.1:5000/](http://127.0.0.1:5000/) for an index of api examples
## Setting up a valid Google domain for OpenID+OAuth
You have to have access to a valid domain that google can get to and where you can install an html file.
Visit: https://www.google.com/accounts/ManageDomains
Visit: [https://www.google.com/accounts/ManageDomains](https://www.google.com/accounts/ManageDomains)
Add your domain, follow the rest of their instructions.

Просмотреть файл

@ -28,7 +28,7 @@ oauth.twitter.com.authorize = https://twitter.com/oauth/authenticate
# below for this server.
oauth.facebook.com.app_id = 163981616966631
oauth.facebook.com.app_secret = 78e3bd4ab991ccf50fb9220452eb30b4
oauth.facebook.com.scope = publish_stream,offline_access
oauth.facebook.com.scope = publish_stream,offline_access,user_groups
oauth.facebook.com.authorize = https://graph.facebook.com/oauth/authorize
oauth.facebook.com.access = https://graph.facebook.com/oauth/access_token
@ -44,10 +44,16 @@ oauth.google.com.scope = https://mail.google.com/ http://www.google.com/m8/feeds
# also set verified = 1
oauth.yahoo.com.consumer_key = dj0yJmk9TjFpSlVBcmY2Q2pnJmQ9WVdrOWQwUjVVVFJKTkdVbWNHbzlNVEF6TnpZME1ERTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD1hZg--
oauth.yahoo.com.consumer_secret = a47367578f07e3ea1ddb045b3003a9c7d95a5f69
oauth.yahoo.com.app_id = wDyQ4I4e
oauth.yahoo.com.app_id = wDyQ4I4e
# set to true if you have completed domain verification with Yahoo
oauth.yahoo.com.verified = 1
oauth.linkedin.com.consumer_key = sz-cmZ24vIXHAK_3NCsNTsF57F3wrgi0uT0vr5NC6hmXWAdmVSFrGcKUNBqDgjP5
oauth.linkedin.com.consumer_secret = RfvZProhTuRAjuOA8EBm7PVfhZO31W2QdLHGd12nfh7hpAwc7VuZiG15pEwFhRRh
oauth.linkedin.com.request = https://api.linkedin.com/uas/oauth/requestToken
oauth.linkedin.com.access = https://api.linkedin.com/uas/oauth/accessToken
oauth.linkedin.com.authorize = https://api.linkedin.com/uas/oauth/authorize
[server:main]
use = egg:Paste#http
host = 127.0.0.1
@ -89,7 +95,7 @@ use = egg:Paste#urlmap
/api = api
[app:home]
use = egg:Paste#static
use = egg:linkdrop#static
document_root = %(here)s/web
[app:api]

Просмотреть файл

@ -27,6 +27,7 @@
<html lang="en">
<head>
<title>F1 not available</title>
<style type="text/css">
* {
margin: 0;
@ -40,59 +41,57 @@
font-style: inherit;
font-size: 100%;
vertical-align: top;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
list-style-type: none;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
body {
font-size: 11px;
font-family: "Lucida Grande", Verdana, sans-serif;
max-height: 113px;
overflow: hidden;
background-color: #fff;
background-position: bottom center;
background-repeat: no-repeat;
background-color: #fff;
}
div.status {
min-height: 113px;
padding: 0 10px;
overflow: hidden;
border-bottom: 1px solid #777;
}
div.status {
position: absolute;
width: 100%;
height: 113px;
line-height: 113px;
top: 0;
left: 0;
width: 400px;
height: 180px;
color: #0a0a0a;
font-size: 14px;
text-align: center;
position: relative;
}
div.status.intermediate.error {
background-color: rgba(255,115,0,0.75);
color: #FFFFFF;
-webkit-box-shadow: 0 0 200px rgba(0, 0, 0, 0.25) inset;
-moz-box-shadow: 0 0 200px rgba(0, 0, 0, 0.25) inset;
box-shadow: 0 0 200px rgba(0, 0, 0, 0.25) inset;
}
#statusErrorMessage {
display: inline-block;
margin-top: 3px;
table {
width: 100%;
height: 100%;
padding: 10px;
}
#statusServerError {
line-height: 20px;
table td {
vertical-align: middle;
}
</style>
</head>
<body>
<div class="status intermediate error">
Sorry, the F1 service is not available at the moment. Please try later.
<table>
<tr>
<td>
Sorry, the F1 service is not available at the moment.<br>Please try later.
</td>
</tr>
</table>
</div>
</body>
</html>

Просмотреть файл

@ -77,6 +77,7 @@
accesskey="&ffshareContext.accesskey;"
command="cmd_openSharePage"/>
</popup>
</popupset>
@ -118,6 +119,7 @@
class="toolbarbutton-1 chromeclass-toolbar-additional"
label="&ffshareToolbarButton.label;"
tooltiptext="&ffshareToolbarButton.tooltip;"
type="checkbox"
command="cmd_openSharePage"/>
<tabbrowser id="content"/>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -2,5 +2,5 @@
<!ENTITY ffshareContext.accesskey "S">
<!ENTITY ffshareMenu.label "Share Page…">
<!ENTITY ffshareMenu.accesskey "h">
<!ENTITY ffshareToolbarButton.label "Share This Page">
<!ENTITY ffshareToolbarButton.label "F1">
<!ENTITY ffshareToolbarButton.tooltip "Use F1 to share the current page via Twitter, Facebook, and more.">

Просмотреть файл

@ -21,52 +21,17 @@
* Contributor(s):
* */
.ffshare-frame {
-moz-transition: height 0.2s ease-in;
#ffshare-toolbar-button > label {
display: none;
}
#ffshare-toolbar-button
{
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
}
#ffshare-toolbar-button > image {
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
width: auto;
height: auto;
}
#ffshare-popup {
-moz-appearance: none;
-moz-window-shadow: none;
background-color: transparent;
margin-top: -4px;
margin-left: -13px;
padding-right: 35px; /* not quite 50px but looks very close */
min-width: 380px !important;
-moz-border-image: url(chrome://browser/skin/hud-panel.png) 26 18 22 50 / 26px 18px 22px 50px repeat;
color: lightgrey;
}
/* factory reset */
#ffshare-popup * {
border: none;
outline: none;
margin: 0;
padding: 0;
-moz-padding-start: 0px;
-moz-padding-end: 0px;
-moz-margin-start: 0px;
-moz-margin-end: 0px;
-moz-border-radius: 0px;
font-family: sans-serif;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
vertical-align: middle;
-moz-box-sizing: border-box;
list-style-type: none;
}
#ffshare-popup description {
margin: 5px 0;
#ffshare-toolbar-button[firstRun] > image {
list-style-image: url("chrome://ffshare/skin/toolbar-button-glow.png");
}
/* Styles to style the autocomplete results */
@ -74,3 +39,7 @@
.autocomplete-richlistitem[type="ffshare"] .ac-url-box {
display: none !important;
}
.ffshare-panel .panel-inner-arrowcontent {
padding: 0;
}

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 10 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 615 B

После

Ширина:  |  Высота:  |  Размер: 403 B

Просмотреть файл

@ -21,52 +21,17 @@
* Contributor(s):
* */
.ffshare-frame {
-moz-transition: height 0.2s ease-in;
#ffshare-toolbar-button > label {
display: none;
}
#ffshare-toolbar-button
{
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
}
#ffshare-toolbar-button > image {
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
width: auto;
height: auto;
}
#ffshare-popup {
-moz-appearance: none;
-moz-window-shadow: none;
background-color: transparent;
margin-top: -4px;
margin-left: -13px;
padding-right: 35px; /* not quite 50px but looks very close */
min-width: 380px !important;
-moz-border-image: url(chrome://browser/skin/hud-panel.png) 26 18 22 50 / 26px 18px 22px 50px repeat;
color: lightgrey;
}
/* factory reset */
#ffshare-popup * {
border: none;
outline: none;
margin: 0;
padding: 0;
-moz-padding-start: 0px;
-moz-padding-end: 0px;
-moz-margin-start: 0px;
-moz-margin-end: 0px;
-moz-border-radius: 0px;
font-family: sans-serif;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
vertical-align: middle;
-moz-box-sizing: border-box;
list-style-type: none;
}
#ffshare-popup description {
margin: 5px 0;
#ffshare-toolbar-button[firstRun] > image {
list-style-image: url("chrome://ffshare/skin/toolbar-button-glow.png");
}
/* Styles to style the autocomplete results */

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 10 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 390 B

После

Ширина:  |  Высота:  |  Размер: 412 B

Просмотреть файл

@ -1,80 +1,92 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
#ffshare-toolbar-button
{
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
-moz-image-region: rect(0px, 35px, 23px, 0px);
}
#ffshare-toolbar-button[disabled="true"],
#ffshare-toolbar-button[disabled="true"]:active
{
-moz-image-region: rect(23px, 35px, 46px, 0px);
}
#ffshare-toolbar-button:active
{
-moz-image-region: rect(46px, 35px, 69px, 0px);
}
#ffshare-popup {
-moz-appearance: none;
-moz-window-shadow: none;
background-color: transparent;
margin-top: -4px;
margin-left: -13px;
padding-right: 35px; /* not quite 50px but looks very close */
min-width: 380px !important;
-moz-border-image: url(chrome://browser/skin/hud-panel.png) 26 18 22 50 / 26px 18px 22px 50px repeat;
color: lightgrey;
}
/* factory reset */
#ffshare-popup * {
border: none;
outline: none;
margin: 0;
padding: 0;
-moz-padding-start: 0px;
-moz-padding-end: 0px;
-moz-margin-start: 0px;
-moz-margin-end: 0px;
-moz-border-radius: 0px;
font-family: sans-serif;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
vertical-align: middle;
-moz-box-sizing: border-box;
list-style-type: none;
}
#ffshare-popup description {
margin: 5px 0;
font-size: 150%;
font-weight: bold;
}
/* Styles to style the autocomplete results */
.autocomplete-richlistitem[type="ffshare"] .ac-site-icon,
.autocomplete-richlistitem[type="ffshare"] .ac-url-box {
display: none !important;
}
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
#ffshare-toolbar-button {
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
-moz-image-region: rect(0px, 35px, 23px, 0px);
}
#ffshare-toolbar-button[disabled="true"],
#ffshare-toolbar-button[disabled="true"]:active {
-moz-image-region: rect(23px, 35px, 46px, 0px);
}
#ffshare-toolbar-button:active {
-moz-image-region: rect(46px, 35px, 69px, 0px);
}
#ffshare-toolbar-button[checked="true"] {
background: none;
border-color: transparent;
-moz-image-region: rect(46px, 35px, 69px, 0px);
}
#ffshare-toolbar-button[firstRun] {
list-style-image: url("chrome://ffshare/skin/toolbar-button-glow.png");
-moz-image-region: rect(0px, 35px, 23px, 0px);
}
/* Styles to style the autocomplete results */
.autocomplete-richlistitem[type="ffshare"] .ac-site-icon,
.autocomplete-richlistitem[type="ffshare"] .ac-url-box {
display: none !important;
}
.ffshare-panel {
width: 441px; /* note this value hard-coded in overlay.js */
min-width: 441px !important;
min-height: 234px !important;
}
.ffshare-browser {
width: 400px; /* note this value tied to ffshare-panel width as well */
height: 100%;
}
/* Popup Bounding Box */
.doorhanger-rtl {
-moz-appearance: none;
-moz-window-shadow: none;
background-color: transparent;
margin-top: -10px;
margin-left: -16px;
min-width: 280px;
-moz-border-image: url(chrome://browser/skin/hud-panel.png) 26 10 22 50 / 26px 18px 22px 50px repeat;
}
.doorhanger-ltr {
-moz-appearance: none;
-moz-window-shadow: none;
background-color: transparent;
margin-top: -10px;
margin-right: -16px;
min-width: 280px;
-moz-border-image: url(chrome://browser/skin/hud-panel.png) 26 50 22 10 / 26px 50px 22px 18px repeat;
}
.doorhanger-rtl .doorhanger-inner {
margin: 4px 6px 2px -30px;
color: #fff;
}
.doorhanger-ltr .doorhanger-inner {
margin: 4px -33px 2px 6px;
color: #fff;
}

Двоичные данные
extensions/firefox-share/src/chrome/skin/toolbar-button-glow.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 22 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 2.9 KiB

После

Ширина:  |  Высота:  |  Размер: 3.2 KiB

Просмотреть файл

@ -35,7 +35,6 @@ function _() {
_("?loaded");
__defineGetter__("acDataStorage", function() {
delete this.ffshareAutoCompleteData;
Cu.import("resource://ffshare/modules/ffshareAutoCompleteData.js");
return ffshareAutoCompleteData;
});
@ -64,13 +63,16 @@ FFShareAutoComplete.prototype = {
return false;
},
findEmails: function findEmails(query) {
findEmails: function findEmails(query, field) {
_("findEmails", Array.slice(arguments));
let result = Cc["@mozilla.org/autocomplete/simple-result;1"].
createInstance(Ci.nsIAutoCompleteSimpleResult);
result.setSearchString(query);
let datadomain = field.getAttribute('autocompletestore');
if (!datadomain)
return result;
//convert the query to only be for things after the comma.
var parts = query.split(','), previousMatch = '';
@ -83,18 +85,19 @@ FFShareAutoComplete.prototype = {
_("query is now: [" + query + "]");
_("previousMatch is now: " + previousMatch);
let data = acDataStorage.get();
data.forEach(function (item) {
var displayNameLower = item.displayName.toLowerCase(),
emailLower = item.email.toLowerCase();
_("data domain is: "+datadomain);
let data = acDataStorage.get(datadomain) || {};
for (let name in data) {
var displayNameLower = name.toLowerCase(),
emailLower = data[name].email.toLowerCase();
if (displayNameLower.indexOf(query) !== -1 || emailLower.indexOf(query) !== -1) {
result.appendMatch(previousMatch + item.email + ', ',
(displayNameLower === emailLower ? item.email : item.displayName + '<' + item.email + '>'), null, 'ffshare');
if (emailLower)
addr = (displayNameLower === emailLower ? data[name].email : name + '<' + data[name].email + '>');
else
addr = name;
result.appendMatch(previousMatch + addr + ', ', addr , null, 'ffshare');
}
});
}
let resultCode = result.matchCount ? "RESULT_SUCCESS" : "RESULT_NOMATCH";
_("returning autocomplete " +resultCode+ " result with " + result.matchCount + " items");
@ -106,7 +109,7 @@ _("previousMatch is now: " + previousMatch);
_("FFShareAutoComplete search", Array.slice(arguments));
if (this.isShareType(name, field))
return this.findEmails(query);
return this.findEmails(query, field);
return null;
}
};

Просмотреть файл

@ -4,7 +4,7 @@
<em:id>ffshare@mozilla.org</em:id>
<em:type>2</em:type>
<em:name>F1 by Mozilla Labs</em:name>
<em:version>0.7.3</em:version>
<em:version>0.7.4</em:version>
<em:creator>Mozilla</em:creator>
<em:contributor></em:contributor>
<em:homepageURL>http://f1.mozillamessaging.com/</em:homepageURL>
@ -13,8 +13,8 @@
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- Firefox -->
<em:minVersion>3.6</em:minVersion>
<em:maxVersion>4.0b9pre</em:maxVersion>
<em:minVersion>3.6.6</em:minVersion>
<em:maxVersion>4.0b12pre</em:maxVersion>
</Description>
</em:targetApplication>
</Description>

Просмотреть файл

@ -20,16 +20,26 @@
*
* Contributor(s):
* */
const Cu = Components.utils;
let EXPORTED_SYMBOLS = ["ffshareAutoCompleteData"];
let data = [];
let data = {};
function _() {
return; // comment out for verbose debugging
let msg = Array.join(arguments, " ");
dump(msg + "\n");
Cu.reportError(msg);
}
let ffshareAutoCompleteData = {
get: function () {
return data;
get: function (domain) {
_("XXX getting data for "+domain);
return data[domain];
},
set: function (newData) {
data = (newData || []);
set: function (acdata) {
_("XXX setting "+ (acdata.contacts ? acdata.contacts.length : "none") +" contacts for "+acdata.domain);
data[acdata.domain] = (acdata.contacts || []);
}
};

Просмотреть файл

@ -21,6 +21,7 @@
* Shane Caraveo <shane@caraveo.com>
* Myk Melez <myk@mozilla.org>
* Justin Dolske <dolske@mozilla.com>
* Erik Vold <erikvvold@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -39,9 +40,7 @@
/* Inject the People content API into window.navigator objects. */
/* Partly based on code in the Geode extension. */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
let EXPORTED_SYMBOLS = ["InjectorInit"];
@ -127,20 +126,20 @@ let Injector = {
};
// hook up a seperate listener for each xul window
// hook up a separate listener for each xul window
function InjectorInit(window) {
if (window.injector) return;
window.injector = {
providers: [],
onLoad: function() {
var obs = Components.classes["@mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService);
var obs = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
obs.addObserver(this, 'content-document-global-created', false);
},
onUnload: function() {
var obs = Components.classes["@mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService);
var obs = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
obs.removeObserver(this, 'content-document-global-created');
},
@ -152,12 +151,12 @@ function InjectorInit(window) {
observe: function(aSubject, aTopic, aData) {
if (!aSubject.location.href) return;
// is this window a child of OUR XUL window?
var mainWindow = aSubject.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
var mainWindow = aSubject.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
if (mainWindow != window) {
return;
}

Просмотреть файл

@ -99,6 +99,9 @@ Subject line for emails, not supported by all services.
"""),
api_arg('picture', 'string', False, None, None, """
URL to publicly available thumbnail, not supported by all services.
"""),
api_arg('picture_base64', 'string', False, None, None, """
Base 64 encoded PNG version of the picture used for attaching to emails.
"""),
api_arg('description', 'string', False, None, None, """
Site provided description of the shared item, not supported by all services.

Просмотреть файл

@ -27,6 +27,7 @@ from linkdrop.lib.oauth import google_
#from linkdrop.lib.oauth.openidconsumer import OpenIDResponder
from linkdrop.lib.oauth import twitter_
from linkdrop.lib.oauth import yahoo_
from linkdrop.lib.oauth import linkedin_
__all__ = ['get_provider']
@ -36,7 +37,8 @@ _providers = {
facebook_.domain: facebook_,
google_.domain: google_,
"googleapps.com": google_,
yahoo_.domain: yahoo_
yahoo_.domain: yahoo_,
linkedin_.domain: linkedin_
}
def get_provider(provider):

Просмотреть файл

@ -33,13 +33,14 @@ import httplib2
import urllib
import random
import copy
import logging
from pylons import config, request, response, session, tmpl_context as c, url
from pylons.controllers.util import abort, redirect
from linkdrop.lib.oauth.base import OAuth2
domain = 'facebook.com'
log = logging.getLogger(domain)
# this function is a derivative of:
# http://code.activestate.com/recipes/146306-http-client-to-post-using-multipartform-data/
@ -210,36 +211,76 @@ class api():
'status': status})
return error
def rawcall(self, url, body):
def rawcall(self, url, body=None, method="GET"):
url = url +"?"+urllib.urlencode(dict(access_token=self.access_token))
content_type, body = encode_multipart_formdata(body)
headers = {
'Content-type': content_type,
'Content-Length': str(len(body))
}
resp, content = httplib2.Http().request(url, 'POST', headers=headers, body=body)
headers = None
if body:
content_type, body = encode_multipart_formdata(body)
headers = {
'Content-type': content_type,
'Content-Length': str(len(body))
}
resp, content = httplib2.Http().request(url, method=method, headers=headers, body=body)
data = json.loads(content)
result = error = None
if 'id' in data:
result = data
result[domain] = data['id']
elif 'data' in data:
result = data
result[domain] = None
else:
error = self._make_error(data, resp)
return result, error
# feed supports message, picture, link, name, caption, description, source
# map our stuff to theirs
post_map = {
'link': 'link',
'title': 'name',
'description': 'description',
'picture': 'picture',
'caption': 'caption',
'source': 'source'
}
def sendmessage(self, message, options={}):
url = config.get("oauth.facebook.com.feed", "https://graph.facebook.com/me/feed")
direct = options.get('to', None)
if direct:
url = "https://graph.facebook.com/%s/feed" % (direct,)
else:
url = config.get("oauth.facebook.com.feed", "https://graph.facebook.com/me/feed")
body = {
"message": message
}
for ours, yours in self.post_map.items():
if ours in options:
body[yours] = options[ours]
for arg in ['link', 'name', 'description', 'picture']:
if arg in options:
body[arg] = options[arg]
return self.rawcall(url, body)
return self.rawcall(url, body, "POST")
def getcontacts(self, start=0, page=25, group=None):
# for twitter we get only those people who we follow and who follow us
# since this data is used for direct messaging
url = "https://graph.facebook.com/me/groups"
result, error = self.rawcall(url)
if error:
return result, error
groups = []
for group in result['data']:
groups.append({
'displayName': group.get('name'),
'accounts': [{'userid': group.get('id'), 'username': None, 'domain': domain}]
})
connectedto = {
'entry': groups,
'itemsPerPage': len(groups),
'startIndex': 0,
'totalResults': len(groups),
}
return connectedto, None

Просмотреть файл

@ -45,6 +45,7 @@ import gdata.contacts
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.header import Header
from pylons import config, request, response, session, tmpl_context as c, url
@ -193,7 +194,6 @@ class responder(OpenIDResponder):
profile = result_data['profile']
provider = domain
import sys; print >> sys.stderr, "credential provider is ", profile.get('providerName')
if profile.get('providerName').lower() == 'openid':
provider = 'googleapps.com'
userid = profile.get('verifiedEmail','')
@ -285,8 +285,25 @@ class api():
c.description = description
c.message = message
part2 = MIMEText(render('/html_email.mako').encode('utf-8'), 'html')
part2.set_charset('utf-8')
c.thumbnail = (options.get('picture_base64', "") != "")
if c.thumbnail:
part2 = MIMEMultipart('related')
html = MIMEText(render('/html_email.mako').encode('utf-8'), 'html')
html.set_charset('utf-8')
# FIXME: we decode the base64 data just so MIMEImage can re-encode it as base64
image = MIMEImage(base64.b64decode(options.get('picture_base64')), 'png')
image.add_header('Content-Id', '<thumbnail>')
image.add_header('Content-Disposition', 'inline; filename=thumbnail.png')
part2.attach(html)
part2.attach(image)
else:
part2 = MIMEText(render('/html_email.mako').encode('utf-8'), 'html')
part2.set_charset('utf-8')
# get the title, or the long url or the short url or nothing
# wrap these in literal for text email
@ -333,7 +350,7 @@ class api():
return result, error
def getgroup_id(self, group):
url = 'http://www.google.com/m8/feeds/groups/default/full?v=2'
url = 'https://www.google.com/m8/feeds/groups/default/full?v=2'
method = 'GET'
client = oauth.Client(self.consumer, self.oauth_token)
resp, content = client.request(url, method)
@ -347,7 +364,13 @@ class api():
def getcontacts(self, start=0, page=25, group=None):
contacts = []
url = 'http://www.google.com/m8/feeds/contacts/default/full?v=1&max-results=%d' % (page,)
profile = self.account.get('profile', {})
accounts = profile.get('accounts', [{}])
userdomain = 'default'
if accounts[0].get('domain') == 'googleapps.com':
userdomain = accounts[0].get('userid').split('@')[-1]
url = 'http://www.google.com/m8/feeds/contacts/%s/full?v=1&max-results=%d' % (userdomain, page,)
method = 'GET'
if start > 0:
url = url + "&start-index=%d" % (start,)
@ -363,6 +386,7 @@ class api():
# itemsPerPage, startIndex, totalResults
client = oauth.Client(self.consumer, self.oauth_token)
resp, content = client.request(url, method)
if int(resp.status) != 200:
error={"provider": domain,
"message": content,
@ -371,7 +395,6 @@ class api():
return None, error
feed = gdata.contacts.ContactsFeedFromString(content)
from pprint import pprint
for entry in feed.entry:
#print entry.group_membership_info
p = {

Просмотреть файл

@ -0,0 +1,191 @@
import urlparse
import json
import httplib2
import oauth2 as oauth
import logging
from rfc822 import AddressList
from pylons import config, request, response, session, tmpl_context as c, url
from pylons.controllers.util import abort, redirect
from paste.deploy.converters import asbool
from linkdrop.lib.oauth.base import OAuth1, get_oauth_config
from linkdrop.lib.base import render
from linkdrop.lib.helpers import safeHTML, literal
domain = 'linkedin.com'
log = logging.getLogger(domain)
def extract_li_data(user):
poco = {
'displayName': "%s %s" % (user.get('firstName'), user.get('lastName'),),
}
if user.get('publicProfileUrl', False):
poco['urls'] = [ { 'type': u'profile', "primary" : False, "value" : user['publicProfileUrl'] }]
if user.get('siteStandardProfileRequest', False):
poco['urls'] = [ { 'type': u'profile', "primary" : True, "value" : user['siteStandardProfileRequest']['url'] }]
if user.get('pictureUrl', False):
poco['photos'] = [ { 'type': u'profile', "value" : user['pictureUrl'] }]
account = {'domain': domain,
'userid': user.get("id"),
'username': "" }
poco['accounts'] = [account]
return poco
class responder(OAuth1):
"""Handle LinkedId OAuth login/authentication"""
domain = 'linkedin.com'
def __init__(self):
OAuth1.__init__(self, domain)
def _get_credentials(self, access_token):
fields = 'id,first-name,last-name,picture-url,public-profile-url,site-standard-profile-request'
profile_url = "http://api.linkedin.com/v1/people/~:(%s)" % (fields,)
consumer = oauth.Consumer(self.consumer_key, self.consumer_secret)
token = oauth.Token(access_token['oauth_token'], access_token['oauth_token_secret'])
client = oauth.Client(consumer, token)
oauth_request = oauth.Request.from_consumer_and_token(self.consumer, token=token, http_url=profile_url)
oauth_request.sign_request(self.sigmethod, self.consumer, token)
headers = oauth_request.to_header()
headers['x-li-format'] = 'json'
resp, content = httplib2.Http.request(client, profile_url, method='GET', headers=headers)
if resp['status'] != '200':
raise Exception("Error status: %r", resp['status'])
li_profile = json.loads(content)
profile = extract_li_data(li_profile)
result_data = {'profile': profile,
'oauth_token': access_token['oauth_token'],
'oauth_token_secret': access_token['oauth_token_secret']}
return result_data
class api():
def __init__(self, account):
self.config = get_oauth_config(domain)
self.account = account
self.oauth_token = oauth.Token(key=account.get('oauth_token'), secret=account.get('oauth_token_secret'))
self.consumer_key = self.config.get('consumer_key')
self.consumer_secret = self.config.get('consumer_secret')
self.consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
self.sigmethod = oauth.SignatureMethod_HMAC_SHA1()
def rawcall(self, url, body=None, method="GET"):
client = oauth.Client(self.consumer, self.oauth_token)
oauth_request = oauth.Request.from_consumer_and_token(self.consumer, token=self.oauth_token, http_url=url, http_method=method)
oauth_request.sign_request(self.sigmethod, self.consumer, self.oauth_token)
headers = oauth_request.to_header()
headers['x-li-format'] = 'json'
body = json.dumps(body)
headers['Content-type'] = 'application/json'
headers['Content-Length'] = str(len(body))
resp, content = httplib2.Http.request(client, url, method=method, headers=headers, body=body)
data = content and json.loads(content) or resp
result = error = None
status = int(resp['status'])
if status < 200 or status >= 300:
error = data
else:
result = data
return result, error
def sendmessage(self, message, options={}):
direct = options.get('to', 'anyone')
if direct in ('anyone', 'connections-only'):
url = "http://api.linkedin.com/v1/people/~/shares"
body = {
"comment": message,
"content": {
"title": options.get('subject', ''),
"submitted-url": options.get('link', ''),
"submitted-image-url": options.get('picture', ''),
"description": options.get('description', ''),
},
"visibility": {
"code": direct
}
}
else:
# we have to do a direct message, different api
url = "http://api.linkedin.com/v1/people/~/mailbox"
profile = self.account.get('profile', {})
from_email = from_ = profile.get('verifiedEmail')
fullname = profile.get('displayName', None)
to_addrs = AddressList(options['to'])
subject = options.get('subject', config.get('share_subject', 'A web link has been shared with you'))
title = options.get('title', options.get('link', options.get('shorturl', '')))
description = options.get('description', '')[:280]
to_ = []
for a in to_addrs.addresslist:
to_.append({'person': {'_path': '/people/'+a[1] }})
c.safeHTML = safeHTML
c.options = options
# insert the url if it is not already in the message
c.longurl = options.get('link')
c.shorturl = options.get('shorturl')
# get the title, or the long url or the short url or nothing
# wrap these in literal for text email
c.from_name = literal(fullname)
c.subject = literal(subject)
c.from_header = literal(from_)
c.to_header = literal(to_)
c.title = literal(title)
c.description = literal(description)
c.message = literal(message)
text_message = render('/text_email.mako').encode('utf-8')
body = {
'recipients': {'values': to_},
'subject': subject,
'body': text_message
}
return self.rawcall(url, body, method="POST")
def getcontacts(self, start=0, page=25, group=None):
contacts = []
url = 'http://api.linkedin.com/v1/people/~/connections?count=%d' % (page,)
method = 'GET'
if start > 0:
url = url + "&start=%d" % (start,)
result, error = self.rawcall(url, method="GET")
if error:
return result, error
# poco-ize the results
entries = result.get('values')
contacts = []
for entry in entries:
contacts.append(extract_li_data(entry))
connectedto = {
'entry': contacts,
'itemsPerPage': result.get('_count', result.get('_total', 0)),
'startIndex': result.get('_start', 0),
'totalResults': result.get('_total'),
}
return connectedto, error

Просмотреть файл

@ -80,6 +80,12 @@ def twitter_to_poco(user):
poco['photos'] = [ { 'type': u'profile', "value" : user['profile_image_url'] }]
if user.get('created_at', None):
poco['published'] = user['created_at']
account = {'domain': 'twitter.com',
'userid': user['id'],
'username': user['screen_name'] }
poco['accounts'] = [account]
return poco
class responder(OAuth1):
@ -157,7 +163,11 @@ class api():
# some reason we dont have a short url, add the long url
message += " %s" % longurl
result = self.api().statuses.update(status=message)
direct = options.get('to', None)
if direct:
result = self.api().direct_messages.new(text=message, user_id=direct)
else:
result = self.api().statuses.update(status=message)
result[domain] = result['id']
except TwitterHTTPError, exc:
try:
@ -195,4 +205,35 @@ class api():
'status': exc.e.code
}
return result, error
def getcontacts(self, start=0, page=25, group=None):
# for twitter we get only those people who we follow and who follow us
# since this data is used for direct messaging
contacts = []
result = error = None
try:
followers = self.api().statuses.followers()
for follower in followers:
contacts.append(twitter_to_poco(follower))
connectedto = {
'entry': contacts,
'itemsPerPage': len(contacts),
'startIndex': 0,
'totalResults': len(contacts),
}
return connectedto, None
except TwitterHTTPError, exc:
details = "TwitterHTTPError %d" % (exc.e.code)
if exc.e.code != 404:
details = json.load(exc.e)
if 'error' in details:
msg = details['error']
else:
msg = str(details)
error = {'provider': domain,
'message': msg,
'status': exc.e.code
}
return result, error

Просмотреть файл

@ -29,6 +29,7 @@ import httplib2
import json
import copy
from rfc822 import AddressList
import logging
from pylons import config, request, response, session, tmpl_context as c, url
from pylons.controllers.util import abort, redirect
@ -46,6 +47,7 @@ from linkdrop.lib.oauth.base import get_oauth_config
YAHOO_OAUTH = 'https://api.login.yahoo.com/oauth/v2/get_token'
domain = 'yahoo.com'
log = logging.getLogger(domain)
class responder(OpenIDResponder):
def __init__(self, consumer=None, oauth_key=None, oauth_secret=None, request_attributes=None, *args,
@ -100,12 +102,14 @@ class responder(OpenIDResponder):
'userid': userid,
'username': username }
profile['accounts'] = [account]
profile['xoauth_yahoo_guid'] = result_data['xoauth_yahoo_guid']
return result_data
class api():
endpoints = {
"mail":"http://mail.yahooapis.com/ws/mail/v1.1/jsonrpc"
"mail":"http://mail.yahooapis.com/ws/mail/v1.1/jsonrpc",
"contacts":"http://social.yahooapis.com/v1/user/%s/contacts"
}
def __init__(self, account):
@ -117,7 +121,7 @@ class api():
self.consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
self.sigmethod = oauth.SignatureMethod_HMAC_SHA1()
def rawcall(self, url, method, args, options={}):
def jsonrpc(self, url, method, args, options={}):
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
@ -161,6 +165,31 @@ class api():
return result, error
def restcall(self, url, method="GET", body=None):
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
oauth_request = oauth.Request.from_consumer_and_token(self.consumer,
token=self.oauth_token,
http_method=method,
http_url=url)
oauth_request.sign_request(self.sigmethod, self.consumer, self.oauth_token)
headers.update(oauth_request.to_header())
resp, content = httplib2.Http().request(url, method, headers=headers, body=body)
data = content and json.loads(content) or resp
result = error = None
status = int(resp['status'])
if status < 200 or status >= 300:
error = data
else:
result = data
return result, error
def sendmessage(self, message, options={}):
result = error = None
@ -194,6 +223,7 @@ class api():
c.title = title
c.description = description
c.message = message
c.thumbnail = False
html_message = render('/html_email.mako').encode('utf-8')
@ -222,6 +252,42 @@ class api():
"savecopy":1
}]
return self.rawcall(self.endpoints['mail'], 'SendMessage', params, options)
return self.jsonrpc(self.endpoints['mail'], 'SendMessage', params, options)
def getcontacts(self, start=0, page=25, group=None):
profile = self.account.get('profile', {})
guid = profile.get('xoauth_yahoo_guid')
result, error = self.restcall(self.endpoints['contacts'] % (guid,))
if error:
return result, error
ycontacts = result.get('contacts')
people = ycontacts.get('contact', [])
contacts = []
# convert yahoo contacts to poco
for person in people:
poco = {}
for f in person.get('fields', []):
field = f.get('type')
value = f.get('value')
if field == 'name':
if value.get('middleName'):
poco['displayName'] = "%s %s %s" % (value.get('givenName'), value.get('middleName'), value.get('familyName'),)
else:
poco['displayName'] = "%s %s" % (value.get('givenName'), value.get('familyName'),)
elif field == 'email':
poco.setdefault('emails',[]).append({ 'value': value, 'primary': False })
elif field == 'nickname':
poco['nickname'] = value
contacts.append(poco)
connectedto = {
'entry': contacts,
'itemsPerPage': ycontacts.get('count', 0),
'startIndex': ycontacts.get('start', 0),
'totalResults': ycontacts.get('total', 0),
}
return connectedto, None

119
linkdrop/static.py Normal file
Просмотреть файл

@ -0,0 +1,119 @@
import os
import sys
import re
from paste import request
from paste import fileapp
from paste import httpexceptions
from paste.httpheaders import ETAG
version_re = re.compile("/\d+.\d+.\d+/", re.U)
class StaticURLParser(object):
"""
based on Paste.urlparser.StaticURLParser, however we handle an internal
redirect for versioning of static files. This is only intended for
development work, as we serve production from apache/mod_wsgi.
"""
# @@: Should URLParser subclass from this?
def __init__(self, directory, root_directory=None,
cache_max_age=None, version="/dev/"):
self.directory = self.normpath(directory)
self.root_directory = self.normpath(root_directory or directory)
self.cache_max_age = cache_max_age
self.version = version
def normpath(path):
return os.path.normcase(os.path.abspath(path))
normpath = staticmethod(normpath)
def __call__(self, environ, start_response):
path_info = environ.get('PATH_INFO', '')
if not path_info:
return self.add_slash(environ, start_response)
directory = "%s" % self.directory
if not path_info.startswith('/%s/' % self.version) and version_re.match(path_info) is None and directory == self.root_directory:
directory = os.path.join(directory, self.version)
if path_info == '/':
# @@: This should obviously be configurable
filename = 'index.html'
else:
filename = request.path_info_pop(environ)
full = self.normpath(os.path.join(directory, filename))
if not full.startswith(self.root_directory):
# Out of bounds
return self.not_found(environ, start_response)
if not os.path.exists(full):
return self.not_found(environ, start_response)
if os.path.isdir(full):
# @@: Cache?
return self.__class__(full, root_directory=self.root_directory,
version=self.version,
cache_max_age=self.cache_max_age)(environ,
start_response)
if environ.get('PATH_INFO') and environ.get('PATH_INFO') != '/':
return self.error_extra_path(environ, start_response)
if_none_match = environ.get('HTTP_IF_NONE_MATCH')
if if_none_match:
mytime = os.stat(full).st_mtime
if str(mytime) == if_none_match:
headers = []
## FIXME: probably should be
## ETAG.update(headers, '"%s"' % mytime)
ETAG.update(headers, mytime)
start_response('304 Not Modified', headers)
return [''] # empty body
fa = self.make_app(full)
if self.cache_max_age:
fa.cache_control(max_age=self.cache_max_age)
return fa(environ, start_response)
def make_app(self, filename):
return fileapp.FileApp(filename)
def add_slash(self, environ, start_response):
"""
This happens when you try to get to a directory
without a trailing /
"""
url = request.construct_url(environ, with_query_string=False)
url += '/'
if environ.get('QUERY_STRING'):
url += '?' + environ['QUERY_STRING']
exc = httpexceptions.HTTPMovedPermanently(
'The resource has moved to %s - you should be redirected '
'automatically.' % url,
headers=[('location', url)])
return exc.wsgi_application(environ, start_response)
def not_found(self, environ, start_response, debug_message=None):
exc = httpexceptions.HTTPNotFound(
'The resource at %s could not be found'
% request.construct_url(environ),
comment='SCRIPT_NAME=%r; PATH_INFO=%r; looking in %r; debug: %s'
% (environ.get('SCRIPT_NAME'), environ.get('PATH_INFO'),
self.directory, debug_message or '(none)'))
return exc.wsgi_application(environ, start_response)
def error_extra_path(self, environ, start_response):
exc = httpexceptions.HTTPNotFound(
'The trailing path %r is not allowed' % environ['PATH_INFO'])
return exc.wsgi_application(environ, start_response)
def __repr__(self):
return '<%s %r>' % (self.__class__.__name__, self.directory)
def make_static(global_conf, document_root, cache_max_age=None, version="dev"):
"""
Return a WSGI application that serves a directory (configured
with document_root)
cache_max_age - integer specifies CACHE_CONTROL max_age in seconds
"""
if cache_max_age is not None:
cache_max_age = int(cache_max_age)
return StaticURLParser(
document_root, cache_max_age=cache_max_age, version=version)

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -16,11 +16,27 @@
<a target="_blank" style="color:#00A0FF;font-size:16px;" href="${c.longurl}">${c.title}</a>
% endif
</div>
<table style="border:none;border-collapse:collapse;margin:10px 0;width:100%;">
<tbody><tr>
<td style="border-left: 1px solid #666;vertical-align:top;">
% if c.description:
<div class="description" style="font-size:12px;color:#666;margin:7px 0;font-style:italic;padding:0 0 0 15px;border-left:1px solid #666;">
<div class="description" style="font-size:12px;color:#666;font-style:italic;padding:0 0 0 10px;">
${context.write(c.safeHTML(c.description))}
</div>
% endif
</td>
% if c.thumbnail:
<td style="width:1%">
% if c.shorturl:
<a target="_blank" style="color:#00A0FF;font-size:16px;" href="${c.shorturl}">
% elif c.longurl:
<a target="_blank" style="color:#00A0FF;font-size:16px;" href="${c.longurl}">
% endif
<img src="cid:thumbnail" style="padding:1px;border:1px solid #ccc;margin:5px;"/></a>
</td>
% endif
</tr></tbody>
</table>
</div>
<div class="footer" style="font-size:12px;color:#444;">
shared via <a target="_blank" style="color:#006AAA;font-weight:bold;text-decoration:none;" title="Share links with the people that matter to you" href="http://f1.mozillamessaging.com/">Mozilla F1</a> for Firefox &mdash; <span style="color:#666;">"share links with the people that matter to you"</span>

Просмотреть файл

@ -30,7 +30,7 @@ except ImportError:
setup(
name='linkdrop',
version='0.1.6.1',
version='0.1.8',
description='',
author='',
author_email='',
@ -45,9 +45,9 @@ setup(
"python-dateutil",
"python-openid",
"python-memcached",
"twitter",
"gdata", # google api support
"sqlalchemy-migrate>=0.5.4",
"twitter>=1.4.2"
],
setup_requires=["PasteScript>=1.6.3"],
packages=find_packages(exclude=['ez_setup']),
@ -63,6 +63,7 @@ setup(
entry_points="""
[paste.app_factory]
main = linkdrop.config.middleware:make_app
static = linkdrop.static:make_static
[paste.filter_app_factory]
csrf = linkdrop.csrf:make_csrf_filter_app

Просмотреть файл

@ -1,10 +0,0 @@
{
baseUrl: "../../web-static/scripts/",
paths: {
"index": "../index",
"jquery": "requireplugins-jquery-1.4.2"
},
name: "index",
exclude: ['jquery'],
out: '../../web-static/index.js'
}

Просмотреть файл

@ -1,6 +1,6 @@
/**
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/

Просмотреть файл

@ -1,4 +1,4 @@
#!/bin/sh
MYDIR=$(cd $(dirname "$0"); pwd)
MYDIR=`cd \`dirname "$0"\`; pwd`
java -classpath $MYDIR/lib/rhino/js.jar:$MYDIR/lib/closure/compiler.jar org.mozilla.javascript.tools.shell.Main $MYDIR/build.js $MYDIR "$@"

Просмотреть файл

@ -1,4 +1,4 @@
#!/bin/sh
MYDIR=$(cd $(dirname "$0"); pwd)
MYDIR=`cd \`dirname "$0"\`; pwd`
java -classpath $MYDIR/lib/rhino/js.jar:$MYDIR/lib/closure/compiler.jar org.mozilla.javascript.tools.debugger.Main $MYDIR/build.js $MYDIR "$@"

Просмотреть файл

@ -5,10 +5,10 @@
* THIS BUILD FILE WILL NOT WORK. It is referencing paths that probably
* do not exist on your machine. Just use it as a guide.
*
*
*
*/
{
({
//The top level directory that contains your app. If this option is used
//then it assumed your scripts are in a subdirectory under this path.
//This option is not required. If it is not specified, then baseUrl
@ -75,8 +75,8 @@
useStrict: false,
//Specify build pragmas. If the source files contain comments like so:
//>>excludeStart("requireExcludeModify", pragmas.requireExcludeModify);
//>>excludeEnd("requireExcludeModify");
//>>excludeStart("fooExclude", pragmas.fooExclude);
//>>excludeEnd("fooExclude");
//Then the comments that start with //>> are the build pragmas.
//excludeStart/excludeEnd and includeStart/includeEnd work, and the
//the pragmas value to the includeStart or excludeStart lines
@ -84,27 +84,12 @@
//lines should be included or excluded.
pragmas: {
//Indicates require will be included with jquery.
jquery: true,
//Remove require.modify() code
requireExcludeModify: true,
//Remove plugin support from require. The i18n! jsonp! order! and
//text! extensions will not work.
requireExcludePlugin: true,
//Remove the page loaded detection.
requireExcludePageLoad: true
jquery: true
},
//Skip processing for pragmas.
skipPragmas: false,
//If execModules is true, each script is execute in
//full to find the require calls/dependencies, but the code is executed
//in the Rhino JavaScript environment. Set this value to true only
//if the code follows the strict require pattern of wrapping all
//code in a require callback. If you are using jQuery, Prototype or MooTools
//you should not set this value to true. Default is false.
execModules: false,
//If skipModuleInsertion is false, then files that do not use require.def
//to define modules will get a require.def() placeholder inserted for them.
//Also, require.pause/resume calls will be inserted.
@ -125,7 +110,7 @@
//built file unless the locale: section is set above.
{
name: "foo/bar/bop",
//Should the contents of require.js be included in the optimized module.
//Defaults to false.
includeRequire: true,
@ -137,7 +122,7 @@
//contain any of the other build options in this file.
override: {
pragmas: {
requireExcludeModify: true
fooExclude: true
}
}
},
@ -174,5 +159,4 @@
]
}
]
}
})

259
tools/webbuild/requirejs/build/jslib/build.js Normal file → Executable file
Просмотреть файл

@ -1,13 +1,13 @@
/**
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
/*jslint regexp: false, plusplus: false, nomen: false */
/*global java: false, lang: false, fileUtil: false, optimize: false,
load: false, quit: false, print: false, logger: false, require: false,
pragma: false */
pragma: false, parse: false */
"use strict";
@ -21,16 +21,16 @@ var build, buildBaseConfig;
optimize: "closure",
optimizeCss: "standard.keepLines",
inlineText: true,
execModules: false
isBuild: true
};
build = function (args) {
var requireBuildPath, buildFile, baseUrlFile, buildPaths, deps, fileName, fileNames,
prop, props, paths, path, i, fileContents, buildFileContents = "",
doClosure, requireContents, pluginContents, pluginBuildFileContents,
doClosure, requireContents, pluginBuildFileContents,
baseConfig, override, builtRequirePath, cmdConfig, config,
modules, module, moduleName, builtModule;
modules, module, moduleName, builtModule, srcPath, buildContext;
if (!args || args.length < 2) {
print("java -jar path/to/js.jar build.js directory/containing/build.js/ build.js\n" +
"where build.js is the name of the build file (see example.build.js for hints on how to make a build file.");
@ -43,11 +43,11 @@ var build, buildBaseConfig;
if (requireBuildPath.charAt(requireBuildPath.length - 1) !== "/") {
requireBuildPath += "/";
}
["lang", "logger", "fileUtil", "parse", "optimize", "pragma", "build"].forEach(function (path) {
load(requireBuildPath + "jslib/" + path + ".js");
});
//Next args can include a build file path as well as other build args.
//build file path comes first. If it does not contain an = then it is
//a build file path. Otherwise, just all build args.
@ -57,42 +57,47 @@ var build, buildBaseConfig;
} else {
args.splice(0, 1);
}
//Remaining args are options to the build
cmdConfig = build.convertArrayToObject(args);
cmdConfig.buildFile = buildFile;
cmdConfig.requireBuildPath = requireBuildPath;
config = build.createConfig(cmdConfig);
paths = config.paths;
//Load require.js with the build patches.
load(config.requireUrl);
load(requireBuildPath + "jslib/requirePatch.js");
if (!config.out && !config.cssIn) {
//This is not just a one-off file build but a full build profile, with
//lots of files to process.
//First copy all the baseUrl content
fileUtil.copyDir((config.appDir || config.baseUrl), config.dir, /\w/, true);
//Adjust baseUrl if config.appDir is in play, and set up build output paths.
buildPaths = {};
if (config.appDir) {
config.dirBaseUrl = config.dir + config.baseUrl;
config.baseUrl = config.appDir + config.baseUrl;
//All the paths should be inside the appDir
buildPaths = paths;
} else {
config.dirBaseUrl = config.dir;
//If no appDir, then make sure to copy the other paths to this directory.
for (prop in paths) {
if (paths.hasOwnProperty(prop)) {
//Set up build path for each path prefix.
buildPaths[prop] = prop.replace(/\./g, "/");
//Make sure source path is fully formed with baseUrl,
//if it is a relative URL.
srcPath = paths[prop];
if (srcPath.indexOf('/') !== 0 && srcPath.indexOf(':') === -1) {
srcPath = config.baseUrl + srcPath;
}
//Copy files to build area. Copy all files (the /\w/ regexp)
fileUtil.copyDir(paths[prop], config.dirBaseUrl + buildPaths[prop], /\w/, true);
fileUtil.copyDir(srcPath, config.dirBaseUrl + buildPaths[prop], /\w/, true);
}
}
}
@ -106,12 +111,13 @@ var build, buildBaseConfig;
baseUrl: config.baseUrl,
paths: paths
});
buildContext = require.s.contexts._;
modules = config.modules;
if (modules) {
modules.forEach(function (module) {
if (module.name) {
module._sourcePath = require.nameToUrl(module.name, null, require.s.ctxName);
module._sourcePath = buildContext.nameToUrl(module.name);
//If the module does not exist, and this is not a "new" module layer,
//as indicated by a true "create" property on the module, then throw an error.
if (!(new java.io.File(module._sourcePath)).exists() && !module.create) {
@ -138,11 +144,11 @@ var build, buildBaseConfig;
};
lang.mixin(baseConfig, config);
require(baseConfig);
if (modules) {
modules.forEach(function (module) {
if (module.name) {
module._buildPath = require.nameToUrl(module.name, null, require.s.ctxName);
module._buildPath = buildContext.nameToUrl(module.name, null);
if (!module.create) {
fileUtil.copyFile(module._sourcePath, module._buildPath);
}
@ -214,16 +220,16 @@ var build, buildBaseConfig;
//Normal optimizations across modules.
//JS optimizations.
fileNames = fileUtil.getFilteredFileList(config.dir, /\.js$/, true);
fileNames = fileUtil.getFilteredFileList(config.dir, /\.js$/, true);
for (i = 0; (fileName = fileNames[i]); i++) {
optimize.jsFile(fileName, fileName, config);
}
//CSS optimizations
if (config.optimizeCss && config.optimizeCss !== "none") {
optimize.css(config.dir, config);
}
//All module layers are done, write out the build.txt file.
fileUtil.saveUtf8File(config.dir + "build.txt", buildFileContents);
}
@ -237,7 +243,7 @@ var build, buildBaseConfig;
if (buildFileContents) {
print(buildFileContents);
}
};
/**
@ -281,6 +287,17 @@ var build, buildBaseConfig;
return result; //Object
};
build.makeAbsPath = function (path, absFilePath) {
//Add abspath if necessary. If path starts with a slash or has a colon,
//then already is an abolute path.
if (path.indexOf('/') !== 0 && path.indexOf(':') === -1) {
path = absFilePath +
(absFilePath.charAt(absFilePath.length - 1) === '/' ? '' : '/') +
path;
}
return path;
};
/**
* Creates a config object for an optimization build.
* It will also read the build profile if it is available, to create
@ -295,7 +312,7 @@ var build, buildBaseConfig;
build.createConfig = function (cfg) {
/*jslint evil: true */
var config = {}, baseUrl, buildFileContents, buildFileConfig,
paths, props, i, prop;
paths, props, i, prop, buildFile, absFilePath, originalBaseUrl;
lang.mixin(config, buildBaseConfig);
lang.mixin(config, cfg, true);
@ -313,20 +330,19 @@ var build, buildBaseConfig;
if (config.buildFile) {
//A build file exists, load it to get more config.
config.buildFile = new java.io.File(config.buildFile).getAbsoluteFile();
buildFile = new java.io.File(config.buildFile).getAbsoluteFile();
//Find the build file, and make sure it exists, if this is a build
//that has a build profile, and not just command line args with an in=path
if (!config.buildFile.exists()) {
throw new Error("ERROR: build file does not exist: " + config.buildFile.getAbsolutePath());
if (!buildFile.exists()) {
throw new Error("ERROR: build file does not exist: " + buildFile.getAbsolutePath());
}
config.baseUrl = fileUtil.absPath(config.buildFile.getParentFile());
config.buildFile = fileUtil.absPath(config.buildFile);
absFilePath = config.baseUrl = fileUtil.absPath(buildFile.getParentFile()).replace(lang.backSlashRegExp, '/');
config.dir = config.baseUrl + "/build/";
//Load build file options.
buildFileContents = fileUtil.readFile(config.buildFile);
buildFileContents = fileUtil.readFile(buildFile);
buildFileConfig = eval("(" + buildFileContents + ")");
lang.mixin(config, buildFileConfig, true);
@ -334,7 +350,6 @@ var build, buildBaseConfig;
//args should take precedence over build file values.
lang.mixin(config, cfg, true);
} else {
//Base URL is relative to the in file.
if (!config.out && !config.cssIn) {
throw new Error("ERROR: 'out' or 'cssIn' option missing.");
}
@ -347,6 +362,9 @@ var build, buildBaseConfig;
if (!config.cssIn && !cfg.baseUrl) {
throw new Error("ERROR: 'baseUrl' option missing.");
}
//In this scenario, the absFile path is current directory
absFilePath = (String((new java.io.File('.')).getAbsolutePath())).replace(lang.backSlashRegExp, '/');
}
if (config.out && !config.cssIn) {
@ -377,7 +395,8 @@ var build, buildBaseConfig;
}
//Adjust the path properties as appropriate.
//First make sure build paths use front slashes and end in a slash
//First make sure build paths use front slashes and end in a slash,
//and make sure they are aboslute paths.
props = ["appDir", "dir", "baseUrl"];
for (i = 0; (prop = props[i]); i++) {
if (config[prop]) {
@ -385,6 +404,34 @@ var build, buildBaseConfig;
if (config[prop].charAt(config[prop].length - 1) !== "/") {
config[prop] += "/";
}
//Add abspath if necessary.
if (prop === "baseUrl") {
originalBaseUrl = config.baseUrl;
if (config.appDir) {
//If baseUrl with an appDir, the baseUrl is relative to
//the appDir, *not* the absFilePath. appDir and dir are
//made absolute before baseUrl, so this will work.
config.baseUrl = build.makeAbsPath(originalBaseUrl, config.appDir);
//Set up dir output baseUrl.
config.dirBaseUrl = build.makeAbsPath(originalBaseUrl, config.dir);
} else {
//The dir output baseUrl is same as regular baseUrl, both
//relative to the absFilePath.
config.baseUrl = build.makeAbsPath(config[prop], absFilePath);
config.dirBaseUrl = config.dir;
}
} else {
config[prop] = build.makeAbsPath(config[prop], absFilePath);
}
}
}
//Make sure some other paths are absolute.
props = ["out", "cssIn"];
for (i = 0; (prop = props[i]); i++) {
if (config[prop]) {
config[prop] = build.makeAbsPath(config[prop], absFilePath);
}
}
@ -436,7 +483,7 @@ var build, buildBaseConfig;
/**
* Uses the module build config object to trace the dependencies for the
* given module.
*
*
* @param {Object} module the module object from the build config info.
* @param {Object} the build config object.
*
@ -445,7 +492,7 @@ var build, buildBaseConfig;
*/
build.traceDependencies = function (module, config) {
var include, override, url, layer, prop,
context = require.s.contexts[require.s.ctxName],
context = require.s.contexts._,
baseConfig = context.config;
//Reset some state set up in requirePatch.js, and clean up require's
@ -475,45 +522,24 @@ var build, buildBaseConfig;
//but grab the latest value from inside require() since it was reset
//since our last context reference.
layer = require._layer;
layer.specified = require.s.contexts[require.s.ctxName].specified;
//Add any other files that did not have an explicit name on them.
//These are files that do not call back into require when loaded.
for (prop in layer.buildPathMap) {
if (layer.buildPathMap.hasOwnProperty(prop)) {
url = layer.buildPathMap[prop];
//Always store the url to module name mapping for use later,
//particularly for anonymous modules and tracking down files that
//did not call require.def to define a module
layer.buildFileToModule[url] = prop;
if (!layer.loadedFiles[url]) {
//Do not add plugins to build file paths since they will
//be added later, near the top of the module layer.
if (prop.indexOf("require/") !== 0) {
layer.buildFilePaths.push(url);
}
layer.loadedFiles[url] = true;
}
}
}
layer.specified = context.specified;
//Reset config
if (module.override) {
require(baseConfig);
}
return layer;
};
/**
* Uses the module build config object to create an flattened version
* of the module, with deep dependencies included.
*
*
* @param {Object} module the module object from the build config info.
*
* @param {Object} layer the layer object returned from build.traceDependencies.
*
*
* @param {Object} the build config object.
*
* @returns {Object} with two properties: "text", the text of the flattened
@ -522,10 +548,15 @@ var build, buildBaseConfig;
*/
build.flattenModule = function (module, layer, config) {
var buildFileContents = "", requireContents = "",
pluginContents = "", pluginBuildFileContents = "", includeRequire,
anonDefRegExp = /require\s*\.\s*def\s*\(\s*(\[|f|\{)/,
context = require.s.contexts._,
//This regexp is not bullet-proof, and it has one optional part to
//avoid issues with some Dojo transition modules that use a
//define(\n//begin v1.x content
//for a comment.
anonDefRegExp = /(require\s*\.\s*def|define)\s*\(\s*(\/\/[^\n\r]*[\r\n])?(\[|f|\{)/,
prop, path, reqIndex, fileContents, currContents,
i, moduleName, specified, deps;
i, moduleName, specified, deps, includeRequire,
parts, builder;
//Use override settings, particularly for pragmas
if (module.override) {
@ -540,8 +571,6 @@ var build, buildBaseConfig;
//If the file wants require.js added to the module, add it now
requireContents = "";
pluginContents = "";
pluginBuildFileContents = "";
includeRequire = false;
if ("includeRequire" in module) {
includeRequire = module.includeRequire;
@ -551,25 +580,6 @@ var build, buildBaseConfig;
buildFileContents += "require.js\n";
}
//Check for any plugins loaded, and hoist to the top, but below
//the require() definition.
specified = layer.specified;
for (prop in specified) {
if (specified.hasOwnProperty(prop)) {
if (prop.indexOf("require/") === 0) {
path = layer.buildPathMap[prop];
if (path) {
pluginBuildFileContents += path.replace(config.dir, "") + "\n";
pluginContents += pragma.process(path, fileUtil.readFile(path), config);
}
}
}
}
if (includeRequire) {
//require.js will be included so the plugins will appear right after it.
buildFileContents += pluginBuildFileContents;
}
//If there was an existing file with require in it, hoist to the top.
if (!includeRequire && layer.existingRequireUrl) {
reqIndex = layer.buildFilePaths.indexOf(layer.existingRequireUrl);
@ -584,41 +594,46 @@ var build, buildBaseConfig;
for (i = 0; (path = layer.buildFilePaths[i]); i++) {
moduleName = layer.buildFileToModule[path];
//Add the contents but remove any pragmas.
currContents = pragma.process(path, fileUtil.readFile(path), config);
//If anonymous module, insert the module name.
currContents = currContents.replace(anonDefRegExp, function (match, suffix) {
layer.modulesWithNames[moduleName] = true;
//Look for CommonJS require calls inside the function if this is
//an anonymous require.def call that just has a function registered.
deps = null;
if (suffix.indexOf('f') !== -1) {
deps = parse.getAnonDeps(path, currContents);
if (deps.length) {
deps = deps.map(function (dep) {
return "'" + dep + "'";
});
} else {
deps = null;
}
//Figure out if the module is a result of a build plugin, and if so,
//then delegate to that plugin.
parts = context.makeModuleMap(moduleName);
builder = parts.prefix && require.pluginBuilders[parts.prefix];
if (builder) {
if (builder.write) {
builder.write(parts.prefix, parts.name, function (input) {
fileContents += input;
});
}
} else {
//Add the contents but remove any pragmas.
currContents = pragma.process(path, fileUtil.readFile(path), config);
//Adust module name if it is for a plugin
if (require.s.contexts._.defPlugin[moduleName]) {
moduleName = require.s.contexts._.defPlugin[moduleName] + '!' + moduleName;
//Mark that it is a module with a name so do not need
//a stub name insertion for it later.
//If anonymous module, insert the module name.
currContents = currContents.replace(anonDefRegExp, function (match, callName, possibleComment, suffix) {
layer.modulesWithNames[moduleName] = true;
}
return "require.def('" + moduleName + "'," +
(deps ? ('[' + deps.toString() + '],') : '') +
suffix;
});
//Look for CommonJS require calls inside the function if this is
//an anonymous define/require.def call that just has a function registered.
deps = null;
if (suffix.indexOf('f') !== -1) {
deps = parse.getAnonDeps(path, currContents);
fileContents += currContents;
if (deps.length) {
deps = deps.map(function (dep) {
return "'" + dep + "'";
});
} else {
deps = null;
}
}
return "define('" + moduleName + "'," +
(deps ? ('[' + deps.toString() + '],') : '') +
suffix;
});
fileContents += currContents;
}
buildFileContents += path.replace(config.dir, "") + "\n";
//Some files may not have declared a require module, and if so,
@ -626,22 +641,12 @@ var build, buildBaseConfig;
//after the module is processed.
//If we have a name, but no defined module, then add in the placeholder.
if (moduleName && !layer.modulesWithNames[moduleName] && !config.skipModuleInsertion) {
fileContents += 'require.def("' + moduleName + '", function(){});\n';
}
//If we have plugins but are not injecting require.js,
//then need to place the plugins after the require definition,
//if it was found.
if (layer.existingRequireUrl === path && !includeRequire) {
fileContents += pluginContents;
buildFileContents += pluginBuildFileContents;
pluginContents = "";
fileContents += 'define("' + moduleName + '", function(){});\n';
}
}
//Add the require file contents to the head of the file.
fileContents = (requireContents ? requireContents + "\n" : "") +
(pluginContents ? pluginContents + "\n" : "") +
fileContents;
return {

Просмотреть файл

@ -1,6 +1,6 @@
/**
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/

Просмотреть файл

@ -1,6 +1,6 @@
/**
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
@ -34,7 +34,7 @@ var commonJs = {
//Get list of files to convert.
fileList = fileUtil.getFilteredFileList(commonJsPath, /\w/, true);
//Normalize on front slashes and make sure the paths do not end in a slash.
commonJsPath = commonJsPath.replace(/\\/g, "/");
savePath = savePath.replace(/\\/g, "/");
@ -60,7 +60,7 @@ var commonJs = {
//Handle JS files.
if (jsFileRegExp.test(fileName)) {
moduleName = fileName.replace(commonJsPath + "/", "").replace(/\.js$/, "");
fileContents = fileUtil.readFile(fileName);
fileContents = commonJs.convert(prefix + moduleName, fileName, fileContents);
fileUtil.saveUtf8File(convertedFileName, fileContents);
@ -77,10 +77,10 @@ var commonJs = {
* Rhino is available, otherwise a cruder regexp is used. If the regexp
* is used, then the contents may not be executable, but hopefully good
* enough to use to find require() calls.
*
*
* @param {String} fileContents
* @param {String} fileName mostly used for informative reasons if an error.
*
*
* @returns {String} a string of JS with comments removed.
*/
removeComments: function (fileContents, fileName) {
@ -98,7 +98,7 @@ var commonJs = {
* Regexp for testing if there is already a require.def call in the file,
* in which case do not try to convert it.
*/
defRegExp: /require\s*\.\s*def\s*\(/,
defRegExp: /(require\s*\.\s*def|define)\s*\(/,
/**
* Regexp for testing if there is a require([]) or require(function(){})
@ -110,22 +110,24 @@ var commonJs = {
* Does the actual file conversion.
*
* @param {String} moduleName the name of the module to use for the
* require.def call.
*
* define() call.
*
* @param {String} fileName the name of the file.
*
*
* @param {String} fileContents the contents of a file :)
*
* @param {Boolean} skipDeps if true, require("") dependencies
* will not be searched, but the contents will just be wrapped in the
* standard require, exports, module dependencies. Only usable in sync
* environments like Node where the require("") calls can be resolved on
* the fly.
*
* @returns {String} the converted contents
*/
convert: function (moduleName, fileName, fileContents) {
convert: function (moduleName, fileName, fileContents, skipDeps) {
//Strip out comments.
if (commonJs.useLog) {
logger.trace("fileName: " + fileName);
}
try {
var i, deps = [], depName, origDepName, part, pathConverted = {},
prop, reqRegExp, match,
var deps = [], depName, match,
//Remove comments
tempContents = commonJs.removeComments(fileContents, fileName),
baseName = moduleName.split("/");
@ -137,24 +139,26 @@ var commonJs = {
//Set baseName to be one directory higher than moduleName.
baseName.pop();
//Reset the regexp to start at beginning of file. Do this
//since the regexp is reused across files.
commonJs.depRegExp.lastIndex = 0;
//Find dependencies in the code that was not in comments.
while ((match = commonJs.depRegExp.exec(tempContents))) {
depName = match[1];
if (commonJs.useLog) {
logger.trace(" " + depName);
}
if (depName) {
deps.push('"' + depName + '"');
if (!skipDeps) {
//Find dependencies in the code that was not in comments.
while ((match = commonJs.depRegExp.exec(tempContents))) {
depName = match[1];
if (commonJs.useLog) {
logger.trace(" " + depName);
}
if (depName) {
deps.push('"' + depName + '"');
}
}
}
//Construct the wrapper boilerplate.
fileContents = 'require.def(["require", "exports", "module"' +
fileContents = 'define(["require", "exports", "module"' +
(deps.length ? ', ' + deps.join(",") : '') + '], ' +
'function(require, exports, module) {\n' +
(commonJs.logConverted ? 'global._requirejs_logger.trace("Evaluating module: ' + moduleName + '");\n' : "") +

Просмотреть файл

@ -1,6 +1,6 @@
/**
* @license RequireJS Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
//Helper functions to deal with file I/O.
@ -27,187 +27,187 @@ fileUtil.absPath = function (file) {
};
fileUtil.getFilteredFileList = function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsJavaObject) {
//summary: Recurses startDir and finds matches to the files that match regExpFilters.include
//and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
//and it will be treated as the "include" case.
//Ignores files/directories that start with a period (.).
var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
i, file, filePath, ok, dirFiles;
//summary: Recurses startDir and finds matches to the files that match regExpFilters.include
//and do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
//and it will be treated as the "include" case.
//Ignores files/directories that start with a period (.).
var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
i, file, filePath, ok, dirFiles;
topDir = startDir;
if (!startDirIsJavaObject) {
topDir = new java.io.File(startDir);
}
topDir = startDir;
if (!startDirIsJavaObject) {
topDir = new java.io.File(startDir);
}
regExpInclude = regExpFilters.include || regExpFilters;
regExpExclude = regExpFilters.exclude || null;
regExpInclude = regExpFilters.include || regExpFilters;
regExpExclude = regExpFilters.exclude || null;
if (topDir.exists()) {
dirFileArray = topDir.listFiles();
for (i = 0; i < dirFileArray.length; i++) {
file = dirFileArray[i];
if (file.isFile()) {
filePath = file.getPath();
if (makeUnixPaths) {
//Make sure we have a JS string.
filePath = String(filePath);
if (filePath.indexOf("/") === -1) {
filePath = filePath.replace(/\\/g, "/");
}
}
ok = true;
if (regExpInclude) {
ok = filePath.match(regExpInclude);
}
if (ok && regExpExclude) {
ok = !filePath.match(regExpExclude);
}
if (topDir.exists()) {
dirFileArray = topDir.listFiles();
for (i = 0; i < dirFileArray.length; i++) {
file = dirFileArray[i];
if (file.isFile()) {
filePath = file.getPath();
if (makeUnixPaths) {
//Make sure we have a JS string.
filePath = String(filePath);
if (filePath.indexOf("/") === -1) {
filePath = filePath.replace(/\\/g, "/");
}
}
if (ok && !file.getName().match(/^\./)) {
files.push(filePath);
}
} else if (file.isDirectory() && !file.getName().match(/^\./)) {
dirFiles = this.getFilteredFileList(file, regExpFilters, makeUnixPaths, true);
files.push.apply(files, dirFiles);
}
}
}
ok = true;
if (regExpInclude) {
ok = filePath.match(regExpInclude);
}
if (ok && regExpExclude) {
ok = !filePath.match(regExpExclude);
}
return files; //Array
if (ok && !file.getName().match(/^\./)) {
files.push(filePath);
}
} else if (file.isDirectory() && !file.getName().match(/^\./)) {
dirFiles = this.getFilteredFileList(file, regExpFilters, makeUnixPaths, true);
files.push.apply(files, dirFiles);
}
}
}
return files; //Array
};
fileUtil.copyDir = function (/*String*/srcDir, /*String*/destDir, /*RegExp?*/regExpFilter, /*boolean?*/onlyCopyNew) {
//summary: copies files from srcDir to destDir using the regExpFilter to determine if the
//file should be copied. Returns a list file name strings of the destinations that were copied.
regExpFilter |= /\w/;
//summary: copies files from srcDir to destDir using the regExpFilter to determine if the
//file should be copied. Returns a list file name strings of the destinations that were copied.
regExpFilter = regExpFilter || /\w/;
var fileNames = fileUtil.getFilteredFileList(srcDir, regExpFilter, true),
copiedFiles = [], i, srcFileName, destFileName;
var fileNames = fileUtil.getFilteredFileList(srcDir, regExpFilter, true),
copiedFiles = [], i, srcFileName, destFileName;
for (i = 0; i < fileNames.length; i++) {
srcFileName = fileNames[i];
destFileName = srcFileName.replace(srcDir, destDir);
for (i = 0; i < fileNames.length; i++) {
srcFileName = fileNames[i];
destFileName = srcFileName.replace(srcDir, destDir);
if (fileUtil.copyFile(srcFileName, destFileName, onlyCopyNew)) {
copiedFiles.push(destFileName);
}
}
if (fileUtil.copyFile(srcFileName, destFileName, onlyCopyNew)) {
copiedFiles.push(destFileName);
}
}
return copiedFiles.length ? copiedFiles : null; //Array or null
return copiedFiles.length ? copiedFiles : null; //Array or null
};
fileUtil.copyFile = function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
//summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
//srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
var destFile = new java.io.File(destFileName), srcFile, parentDir,
srcChannel, destChannel;
//summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
//srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
var destFile = new java.io.File(destFileName), srcFile, parentDir,
srcChannel, destChannel;
//logger.trace("Src filename: " + srcFileName);
//logger.trace("Dest filename: " + destFileName);
//logger.trace("Src filename: " + srcFileName);
//logger.trace("Dest filename: " + destFileName);
//If onlyCopyNew is true, then compare dates and only copy if the src is newer
//than dest.
if (onlyCopyNew) {
srcFile = new java.io.File(srcFileName);
if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) {
return false; //Boolean
}
}
//If onlyCopyNew is true, then compare dates and only copy if the src is newer
//than dest.
if (onlyCopyNew) {
srcFile = new java.io.File(srcFileName);
if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) {
return false; //Boolean
}
}
//Make sure destination dir exists.
parentDir = destFile.getParentFile();
if (!parentDir.exists()) {
if (!parentDir.mkdirs()) {
throw "Could not create directory: " + parentDir.getAbsolutePath();
}
}
//Make sure destination dir exists.
parentDir = destFile.getParentFile();
if (!parentDir.exists()) {
if (!parentDir.mkdirs()) {
throw "Could not create directory: " + parentDir.getAbsolutePath();
}
}
//Java's version of copy file.
srcChannel = new java.io.FileInputStream(srcFileName).getChannel();
destChannel = new java.io.FileOutputStream(destFileName).getChannel();
destChannel.transferFrom(srcChannel, 0, srcChannel.size());
srcChannel.close();
destChannel.close();
return true; //Boolean
//Java's version of copy file.
srcChannel = new java.io.FileInputStream(srcFileName).getChannel();
destChannel = new java.io.FileOutputStream(destFileName).getChannel();
destChannel.transferFrom(srcChannel, 0, srcChannel.size());
srcChannel.close();
destChannel.close();
return true; //Boolean
};
fileUtil.readFile = function (/*String*/path, /*String?*/encoding) {
//summary: reads a file and returns a string
encoding = encoding || "utf-8";
var file = new java.io.File(path),
lineSeparator = fileUtil.getLineSeparator(),
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
stringBuffer, line;
try {
stringBuffer = new java.lang.StringBuffer();
line = input.readLine();
//summary: reads a file and returns a string
encoding = encoding || "utf-8";
var file = new java.io.File(path),
lineSeparator = fileUtil.getLineSeparator(),
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
stringBuffer, line;
try {
stringBuffer = new java.lang.StringBuffer();
line = input.readLine();
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
// http://www.unicode.org/faq/utf_bom.html
// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
if (line && line.length() && line.charAt(0) === 0xfeff) {
// Eat the BOM, since we've already found the encoding on this file,
// and we plan to concatenating this buffer with others; the BOM should
// only appear at the top of a file.
line = line.substring(1);
}
while (line !== null) {
stringBuffer.append(line);
stringBuffer.append(lineSeparator);
line = input.readLine();
}
//Make sure we return a JavaScript string and not a Java string.
return String(stringBuffer.toString()); //String
} finally {
input.close();
}
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
// http://www.unicode.org/faq/utf_bom.html
// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
if (line && line.length() && line.charAt(0) === 0xfeff) {
// Eat the BOM, since we've already found the encoding on this file,
// and we plan to concatenating this buffer with others; the BOM should
// only appear at the top of a file.
line = line.substring(1);
}
while (line !== null) {
stringBuffer.append(line);
stringBuffer.append(lineSeparator);
line = input.readLine();
}
//Make sure we return a JavaScript string and not a Java string.
return String(stringBuffer.toString()); //String
} finally {
input.close();
}
};
fileUtil.saveUtf8File = function (/*String*/fileName, /*String*/fileContents) {
//summary: saves a file using UTF-8 encoding.
fileUtil.saveFile(fileName, fileContents, "utf-8");
//summary: saves a file using UTF-8 encoding.
fileUtil.saveFile(fileName, fileContents, "utf-8");
};
fileUtil.saveFile = function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
//summary: saves a file.
var outFile = new java.io.File(fileName), outWriter, parentDir, os;
parentDir = outFile.getAbsoluteFile().getParentFile();
if (!parentDir.exists()) {
if (!parentDir.mkdirs()) {
throw "Could not create directory: " + parentDir.getAbsolutePath();
}
}
if (encoding) {
outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding);
} else {
outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
}
//summary: saves a file.
var outFile = new java.io.File(fileName), outWriter, parentDir, os;
os = new java.io.BufferedWriter(outWriter);
try {
os.write(fileContents);
} finally {
os.close();
}
parentDir = outFile.getAbsoluteFile().getParentFile();
if (!parentDir.exists()) {
if (!parentDir.mkdirs()) {
throw "Could not create directory: " + parentDir.getAbsolutePath();
}
}
if (encoding) {
outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile), encoding);
} else {
outWriter = new java.io.OutputStreamWriter(new java.io.FileOutputStream(outFile));
}
os = new java.io.BufferedWriter(outWriter);
try {
os.write(fileContents);
} finally {
os.close();
}
};
fileUtil.deleteFile = function (/*String*/fileName) {
//summary: deletes a file or directory if it exists.
var file = new java.io.File(fileName), files, i;
if (file.exists()) {
if (file.isDirectory()) {
files = file.listFiles();
for (i = 0; i < files.length; i++) {
this.deleteFile(files[i]);
}
}
file["delete"]();
}
//summary: deletes a file or directory if it exists.
var file = new java.io.File(fileName), files, i;
if (file.exists()) {
if (file.isDirectory()) {
files = file.listFiles();
for (i = 0; i < files.length; i++) {
this.deleteFile(files[i]);
}
}
file["delete"]();
}
};

Просмотреть файл

@ -1,6 +1,6 @@
/**
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/

Просмотреть файл

@ -1,6 +1,6 @@
/**
* @license RequireJS Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
var logger = {

Просмотреть файл

@ -1,10 +1,10 @@
/**
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
/*jslint plusplus: false */
/*jslint plusplus: false, nomen: false, regexp: false */
/*global require: false, java: false, Packages: false, logger: false, fileUtil: false,
readFile: false, lang: false */
@ -14,8 +14,6 @@ var optimize;
(function () {
var JSSourceFilefromCode,
textDepRegExp = /["'](text)\!([^"']+)["']/g,
relativeDefRegExp = /require\s*\.\s*def\s*\(\s*['"]([^'"]+)['"]/g,
cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/g,
cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g;
@ -30,18 +28,6 @@ var optimize;
return JSSourceFilefromCode.invoke(null, [filename, content]);
}
//Adds escape sequences for non-visual characters, double quote and backslash
//and surrounds with double quotes to form a valid string literal.
//Assumes the string will be in a single quote string value.
function jsEscape(text) {
return text.replace(/(['\\])/g, '\\$1')
.replace(/[\f]/g, "\\f")
.replace(/[\b]/g, "\\b")
.replace(/[\n]/g, "\\n")
.replace(/[\t]/g, "\\t")
.replace(/[\r]/g, "\\r");
}
/**
* If an URL from a CSS url value contains start/end quotes, remove them.
* This is not done in the regexp, since my regexp fu is not that strong,
@ -85,9 +71,9 @@ var optimize;
if (mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) !== "all")) {
return fullMatch;
}
importFileName = cleanCssUrlQuotes(importFileName);
//Ignore the file import if it is part of an ignore list.
if (cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") !== -1) {
return fullMatch;
@ -95,7 +81,7 @@ var optimize;
//Make sure we have a unix path for the rest of the operation.
importFileName = importFileName.replace(lang.backSlashRegExp, "/");
try {
//if a relative path, then tack on the filePath.
//If it is not a relative path, then the readFile below will fail,
@ -118,7 +104,7 @@ var optimize;
importContents = importContents.replace(cssUrlRegExp, function (fullMatch, urlMatch) {
fixedUrlMatch = cleanCssUrlQuotes(urlMatch);
fixedUrlMatch = fixedUrlMatch.replace(lang.backSlashRegExp, "/");
//Only do the work for relative URLs. Skip things that start with / or have
//a protocol.
colonIndex = fixedUrlMatch.indexOf(":");
@ -141,10 +127,10 @@ var optimize;
}
}
}
return "url(" + parts.join("/") + ")";
});
return importContents;
} catch (e) {
logger.trace(fileName + "\n Cannot inline css import, skipping: " + importFileName);
@ -154,101 +140,38 @@ var optimize;
}
optimize = {
closure: function (fileName, fileContents, keepLines) {
closure: function (fileName, fileContents, keepLines, config) {
config = config || {};
var jscomp = Packages.com.google.javascript.jscomp,
flags = Packages.com.google.common.flags,
//Fake extern
externSourceFile = closurefromCode("fakeextern.js", " "),
//Set up source input
jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
options, FLAG_compilation_level, compiler,
options, option, FLAG_compilation_level, compiler,
Compiler = Packages.com.google.javascript.jscomp.Compiler;
logger.trace("Minifying file: " + fileName);
//Set up options
options = new jscomp.CompilerOptions();
options.prettyPrint = keepLines;
for (option in config.CompilerOptions) {
// options are false by default and jslint wanted an if statement in this for loop
if (config.CompilerOptions[option]) {
options[option] = config.CompilerOptions[option];
}
FLAG_compilation_level = flags.Flag.value(jscomp.CompilationLevel.SIMPLE_OPTIMIZATIONS);
}
options.prettyPrint = keepLines || options.prettyPrint;
FLAG_compilation_level = flags.Flag.value(jscomp.CompilationLevel[config.CompilationLevel || 'SIMPLE_OPTIMIZATIONS']);
FLAG_compilation_level.get().setOptionsForCompilationLevel(options);
//Trigger the compiler
Compiler.setLoggingLevel(Packages.java.util.logging.Level.WARNING);
Compiler.setLoggingLevel(Packages.java.util.logging.Level[config.loggingLevel || 'WARNING']);
compiler = new Compiler();
compiler.compile(externSourceFile, jsSourceFile, options);
return compiler.toSource();
},
//Inlines text! dependencies.
inlineText: function (fileName, fileContents) {
return fileContents.replace(textDepRegExp, function (match, prefix, dep, offset) {
var parts, modName, ext, strip, content, normalizedName, index,
defSegment, defStart, defMatch, tempMatch, defName;
parts = dep.split("!");
modName = parts[0];
ext = "";
strip = parts[1];
content = parts[2];
//Extension is part of modName
index = modName.lastIndexOf(".");
if (index !== -1) {
ext = modName.substring(index + 1, modName.length);
modName = modName.substring(0, index);
}
//Adjust the text path to be a full name, not a relative
//one, if needed.
normalizedName = modName;
if (modName.charAt(0) === ".") {
//Need to backtrack an arbitrary amount in the file
//to find the require.def call
//that includes this relative name, to find what path to use
//for the relative part.
defStart = offset - 1000;
if (defStart < 0) {
defStart = 0;
}
defSegment = fileContents.substring(defStart, offset);
//Take the last match, the one closest to current text! string.
relativeDefRegExp.lastIndex = 0;
while ((tempMatch = relativeDefRegExp.exec(defSegment)) !== null) {
defMatch = tempMatch;
}
if (!defMatch) {
throw new Error("Cannot resolve relative dependency: " + dep + " in file: " + fileName);
}
//Take the last match, the one closest to current text! string.
defName = defMatch[1];
normalizedName = require.normalizeName(modName, defName);
}
if (strip !== "strip") {
content = strip;
strip = null;
}
if (content) {
//Already an inlined resource, return.
return match;
} else {
content = readFile(require.nameToUrl(normalizedName, "." + ext, require.s.ctxName));
if (strip) {
content = require.textStrip(content);
}
return "'" + prefix +
"!" + modName +
(ext ? "." + ext : "") +
(strip ? "!strip" : "") +
"!" + jsEscape(content) + "'";
}
});
return compiler.toSource();
},
/**
@ -265,24 +188,14 @@ var optimize;
var doClosure = (config.optimize + "").indexOf("closure") === 0,
fileContents;
if (config.inlineText && !optimize.textLoaded) {
//Make sure text extension is loaded.
require(["require/text"]);
optimize.textLoaded = true;
}
fileContents = fileUtil.readFile(fileName);
//Inline text files.
if (config.inlineText) {
fileContents = optimize.inlineText(fileName, fileContents);
}
//Optimize the JS files if asked.
if (doClosure) {
fileContents = optimize.closure(fileName,
fileContents,
(config.optimize.indexOf(".keepLines") !== -1));
(config.optimize.indexOf(".keepLines") !== -1),
config.closure);
}
fileUtil.saveUtf8File(outFileName, fileContents);
@ -341,7 +254,7 @@ var optimize;
*/
css: function (startDir, config) {
if (config.optimizeCss.indexOf("standard") !== -1) {
var i, fileName, startIndex, endIndex, originalFileContents, fileContents,
var i, fileName,
fileList = fileUtil.getFilteredFileList(startDir, /\.css$/, true);
if (fileList) {
for (i = 0; i < fileList.length; i++) {

Просмотреть файл

@ -1,6 +1,6 @@
/**
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
@ -47,6 +47,26 @@ var parse;
return String(node.getString());
}
/**
* Calls compiler.parse, and if any errors, throws.
*/
function compilerParse(jsSourceFile, fileName) {
var result = compiler.parse(jsSourceFile),
errorManager = compiler.getErrorManager(),
errorMsg = '', errors, i;
if (errorManager.getErrorCount() > 0) {
errorMsg += 'ERROR(S) in file: ' + fileName + ':\n';
errors = errorManager.getErrors();
for (i = 0; i < errors.length; i++) {
errorMsg += errors[i].toString() + '\n';
}
throw new Error(errorMsg);
}
return result;
}
/**
* Validates a node as being an object literal (like for i18n bundles)
* or an array literal with just string members.
@ -60,7 +80,7 @@ var parse;
return true;
}
//Dependencies can be an object literal or an array.
//Dependencies can be an object literal or an array.
if (type !== ARRAYLIT) {
return false;
}
@ -74,18 +94,18 @@ var parse;
}
/**
* Main parse function. Returns a string of any valid require or require.def
* Main parse function. Returns a string of any valid require or define/require.def
* calls as part of one JavaScript source string.
* @param {String} fileName
* @param {String} fileContents
* @returns {String} JS source string or null, if no require or require.def
* @returns {String} JS source string or null, if no require or define/require.def
* calls are found.
*/
parse = function (fileName, fileContents) {
//Set up source input
var matches = [], result = null,
jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
astRoot = compiler.parse(jsSourceFile);
jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
astRoot = compilerParse(jsSourceFile, fileName);
parse.recurse(astRoot, matches);
@ -109,7 +129,7 @@ var parse;
matches.push(parsed);
}
parse.recurse(node, matches);
}
}
};
/**
@ -120,15 +140,15 @@ var parse;
*/
parse.definesRequire = function (fileName, fileContents) {
var jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
astRoot = compiler.parse(jsSourceFile);
astRoot = compilerParse(jsSourceFile, fileName);
return parse.nodeHasRequire(astRoot);
};
/**
* Finds require("") calls inside a CommonJS anonymous module wrapped in a
* require.def(function(require, exports, module){}) wrapper. These dependencies
* will be added to a modified require.def call that lists the dependencies
* define/require.def(function(require, exports, module){}) wrapper. These dependencies
* will be added to a modified define() call that lists the dependencies
* on the outside of the function.
* @param {String} fileName
* @param {String} fileContents
@ -137,10 +157,10 @@ var parse;
*/
parse.getAnonDeps = function (fileName, fileContents) {
var jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
astRoot = compiler.parse(jsSourceFile),
astRoot = compilerParse(jsSourceFile, fileName),
deps = [],
defFunc = parse.findAnonRequireDefCallback(astRoot);
//Now look inside the def call's function for require calls.
if (defFunc) {
parse.findRequireDepNames(defFunc, deps);
@ -174,6 +194,16 @@ var parse;
return func;
}
}
} else if (node.getType() === EXPR_RESULT &&
node.getFirstChild().getType() === CALL &&
node.getFirstChild().getFirstChild().getType() === NAME &&
nodeString(node.getFirstChild().getFirstChild()) === "define") {
func = node.getFirstChild().getFirstChild().getLastSibling();
if (func.getType() === FUNCTION) {
//Bingo.
return func;
}
}
//Check child nodes
@ -253,28 +283,95 @@ var parse;
return false;
};
function optionalString(node) {
var str = null;
if (node) {
str = parse.nodeToString(node);
//Need to trim off trailing ; that is added by nodeToString too.
if (str.charAt(str.length - 1) === ';') {
str = str.slice(0, str.length - 1);
}
}
return str;
}
/**
* Determines if a specific node is a valid require or require.def call.
* Convert a require/require.def/define call to a string if it is a valid
* call via static analysis of dependencies.
* @param {String} callName the name of call (require or define)
* @param {Packages.com.google.javascript.rhino.Node} the config node inside the call
* @param {Packages.com.google.javascript.rhino.Node} the name node inside the call
* @param {Packages.com.google.javascript.rhino.Node} the deps node inside the call
*/
parse.callToString = function (callName, config, name, deps) {
//If name is an array, it means it is an anonymous module,
//so adjust args appropriately. An anonymous module could
//have a FUNCTION as the name type, but just ignore those
//since we just want to find dependencies.
//TODO: CHANGE THIS if/when support using a tostring
//on function to find CommonJS dependencies.
var configString, nameString, depString;
if (name) {
if (name.getType() === ARRAYLIT) {
deps = name;
}
}
if (deps && !validateDeps(deps)) {
return null;
}
//Only serialize the call name, config, module name and dependencies,
//otherwise could get local variable names for module value.
configString = config && config.getType() === OBJECTLIT && optionalString(config);
nameString = optionalString(name);
depString = optionalString(deps);
return callName + "(" +
(configString ? configString : "") +
(nameString ? (configString ? "," : "") + nameString : "") +
(depString ? (configString || nameString ? "," : "") + depString : "") +
");";
};
/**
* Determines if a specific node is a valid require or define/require.def call.
* @param {Packages.com.google.javascript.rhino.Node} node
*
* @returns {String} a JS source string with the valid require call.
*
* @returns {String} a JS source string with the valid require/define call.
* Otherwise null.
*/
parse.parseNode = function (node) {
var call, methodName, targetName, name, deps, callChildCount;
var call, methodName, targetName, name, config, deps, callChildCount;
if (node.getType() === EXPR_RESULT && node.getFirstChild().getType() === CALL) {
call = node.getFirstChild();
if (call.getFirstChild().getType() === NAME &&
nodeString(call.getFirstChild()) === "require") {
//It is a plain require() call.
deps = call.getChildAtIndex(1);
if (!validateDeps(deps)) {
config = call.getChildAtIndex(1);
deps = call.getChildAtIndex(2);
if (config.getType() === ARRAYLIT) {
deps = config;
config = null;
}
if (!deps || !validateDeps(deps)) {
return null;
}
return parse.nodeToString(call);
return parse.callToString("require", null, null, deps);
} else if (call.getType() === CALL &&
call.getFirstChild().getType() === NAME &&
nodeString(call.getFirstChild()) === "define") {
//A define call
name = call.getChildAtIndex(1);
deps = call.getChildAtIndex(2);
return parse.callToString("define", null, name, deps);
} else if (call.getFirstChild().getType() === GETPROP &&
call.getFirstChild().getFirstChild().getType() === NAME &&
@ -289,21 +386,7 @@ var parse;
name = call.getChildAtIndex(1);
deps = call.getChildAtIndex(2);
//If name is an array, it means it is an anonymous module,
//so adjust args appropriately. An anonymous module could
//have a FUNCTION as the name type, but just ignore those
//since we just want to find dependencies.
//TODO: CHANGE THIS if/when support using a tostring
//on function to find CommonJS dependencies.
if (name.getType() === ARRAYLIT) {
deps = name;
}
if (deps && !validateDeps(deps)) {
return null;
}
return parse.nodeToString(call);
return parse.callToString("define", null, name, deps);
} else if (methodName === "modify") {
//A require.modify() call

Просмотреть файл

@ -1,6 +1,6 @@
/**
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
@ -12,6 +12,7 @@
var pragma = {
conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/,
useStrictRegExp: /['"]use strict['"];/g,
hasRegExp: /has\s*\(\s*['"]([^'"]+)['"]\)/g,
removeStrict: function (contents, config) {
return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, '');
@ -27,11 +28,17 @@ var pragma = {
endMarkerIndex, shouldInclude, startLength, pragmas = config.pragmas,
//Legacy arg defined to help in dojo conversion script. Remove later
//when dojo no longer needs conversion:
kwArgs = {
profileProperties: {
hostenvType: "browser"
kwArgs = pragmas;
//Replace has references if desired
if (config.has) {
fileContents = fileContents.replace(pragma.hasRegExp, function (match, test) {
if (test in config.has) {
return !!config.has[test];
}
};
return match;
});
}
//If pragma work is not desired, skip it.
if (config.skipPragmas) {
@ -44,10 +51,10 @@ var pragma = {
if (lineEndIndex === -1) {
lineEndIndex = fileContents.length - 1;
}
//Increment startIndex past the line so the next conditional search can be done.
startIndex = lineEndIndex + 1;
//Break apart the conditional.
conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1);
matches = conditionLine.match(pragma.conditionalRegExp);
@ -66,29 +73,29 @@ var pragma = {
conditionLine +
" failed with this error: " + e;
}
//Find the endpoint marker.
endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g");
endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length));
if (endMatches) {
endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length;
//Find the next line return based on the match position.
lineEndIndex = fileContents.indexOf("\n", endMarkerIndex);
if (lineEndIndex === -1) {
lineEndIndex = fileContents.length - 1;
}
//Should we include the segment?
shouldInclude = ((type === "exclude" && !isTrue) || (type === "include" && isTrue));
//Remove the conditional comments, and optionally remove the content inside
//the conditional comments.
startLength = startIndex - foundIndex;
fileContents = fileContents.substring(0, foundIndex) +
(shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "") +
fileContents.substring(lineEndIndex + 1, fileContents.length);
//Move startIndex to foundIndex, since that is the new position in the file
//where we need to look for more conditionals in the next while loop pass.
startIndex = foundIndex;
@ -97,7 +104,7 @@ var pragma = {
fileName +
". Cannot find end marker for conditional comment: " +
conditionLine;
}
}
}

110
tools/webbuild/requirejs/build/jslib/requirePatch.js Normal file → Executable file
Просмотреть файл

@ -1,6 +1,6 @@
/**
* @license RequireJS Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
/*
@ -9,12 +9,13 @@
/*jslint nomen: false, plusplus: false, regexp: false */
/*global load: false, require: false, logger: false, setTimeout: true,
pragma: false, Packages: false, parse: false, java: true */
pragma: false, Packages: false, parse: false, java: true, define: true */
"use strict";
(function () {
var layer,
lineSeparator = java.lang.System.getProperty("line.separator"),
pluginBuilderRegExp = /(["']?)pluginBuilder(["']?)\s*[=\:]\s*["']([^'"\s]+)["']/,
oldDef;
//A file read function that can deal with BOMs
@ -26,10 +27,10 @@
try {
stringBuffer = new java.lang.StringBuffer();
line = input.readLine();
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
// http://www.unicode.org/faq/utf_bom.html
// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
if (line && line.length() && line.charAt(0) === 0xfeff) {
@ -53,7 +54,7 @@
/** Reset state for each build layer pass. */
require._buildReset = function () {
//Clear up the existing context.
delete require.s.contexts[require.s.ctxName];
delete require.s.contexts._;
//These variables are not contextName-aware since the build should
//only have one context.
@ -77,8 +78,11 @@
*/
require._isSupportedBuildUrl = function (url) {
//Ignore URLs with protocols or question marks, means either network
//access is needed to fetch it or it is too dynamic.
return url.indexOf(":") === -1 && url.indexOf("?") === -1;
//access is needed to fetch it or it is too dynamic. Note that
//on Windows, full paths are used for some urls, which include
//the drive, like c:/something, so need to test for something other
//than just a colon.
return url.indexOf("://") === -1 && url.indexOf("?") === -1;
};
//Override require.def to catch modules that just define an object, so that
@ -89,33 +93,48 @@
//This function signature does not have to be exact, just match what we
//are looking for.
require.def = function (name, obj) {
if (typeof name === "string" && !require.isArray(obj) && !require.isFunction(obj)) {
define = require.def = function (name, obj) {
if (typeof name === "string") {
layer.modulesWithNames[name] = true;
}
return oldDef.apply(require, arguments);
};
//Add some utilities for plugins/pluginBuilders
require._readFile = _readFile;
require._fileExists = function (path) {
return (new java.io.File(path)).exists();
};
require.pluginBuilders = {};
//Override load so that the file paths can be collected.
require.load = function (moduleName, contextName) {
require.load = function (context, moduleName, url) {
/*jslint evil: true */
var url = require.nameToUrl(moduleName, null, contextName), map,
contents,
context = require.s.contexts[contextName];
var isPlugin = false,
contents, pluginBuilderMatch, builderName;
//Adjust the URL if it was not transformed to use baseUrl.
if (require.jsExtRegExp.test(moduleName)) {
url = context.config.dirBaseUrl + url;
}
context.loaded[moduleName] = false;
context.scriptCount += 1;
//Only handle urls that can be inlined, so that means avoiding some
//URLs like ones that require network access or may be too dynamic,
//like JSONP
if (require._isSupportedBuildUrl(url)) {
//Save the module name to path mapping.
map = layer.buildPathMap[moduleName] = url;
//Save the module name to path and path to module name mappings.
layer.buildPathMap[moduleName] = url;
layer.buildFileToModule[url] = moduleName;
//Load the file contents, process for conditionals, then
//evaluate it.
contents = _readFile(url);
contents = pragma.process(url, contents, context.config);
//Find out if the file contains a require() definition. Need to know
//this so we can inject plugins right after it, but before they are needed,
//and to make sure this file is first, so that require.def calls work.
@ -124,29 +143,55 @@
if (!layer.existingRequireUrl && parse.definesRequire(url, contents)) {
layer.existingRequireUrl = url;
}
//Only eval complete contents if asked, or if it is a require extension.
//Otherwise, treat the module as not safe for execution and parse out
//the require calls.
if (!context.config.execModules && moduleName !== "require/text" && moduleName !== "require/i18n") {
//Only find the require parts with [] dependencies and
//evaluate those. This path is useful when the code
//does not follow the strict require pattern of wrapping all
//code in a require callback.
if (moduleName in context.plugins) {
//This is a loader plugin, check to see if it has a build extension,
//otherwise the plugin will act as the plugin builder too.
pluginBuilderMatch = pluginBuilderRegExp.exec(contents);
if (pluginBuilderMatch) {
//Load the plugin builder for the plugin contents.
builderName = context.normalize(pluginBuilderMatch[3], moduleName);
contents = _readFile(context.nameToUrl(builderName));
}
//plugins need to have their source evaled as-is.
isPlugin = true;
}
//Parse out the require and define calls.
//Do this even for plugins in case they have their own
//dependencies that may be separate to how the pluginBuilder works.
if (!isPlugin) {
contents = parse(url, contents);
}
if (contents) {
eval(contents);
//Support anonymous modules.
require.completeLoad(moduleName, context);
context.completeLoad(moduleName);
}
// remember the list of dependencies for this layer.O
layer.buildFilePaths.push(url);
}
//Mark the module loaded.
context.loaded[moduleName] = true;
require.checkLoaded(contextName);
//Get a handle on the pluginBuilder
if (isPlugin) {
require.pluginBuilders[moduleName] = context.defined[moduleName];
}
};
//This method is called when a plugin specifies a loaded value. Use
//this to track dependencies that do not go through require.load.
require.onPluginLoad = function (context, pluginName, name, value) {
var registeredName = pluginName + '!' + name;
layer.buildFilePaths.push(registeredName);
layer.buildFileToModule[registeredName] = registeredName;
layer.modulesWithNames[registeredName] = true;
};
//Override a method provided by require/text.js for loading text files as
@ -162,9 +207,12 @@
require.execCb = function (name, cb, args) {
var url = name && layer.buildPathMap[name];
if (url && !layer.loadedFiles[url]) {
layer.buildFilePaths.push(url);
layer.loadedFiles[url] = true;
layer.modulesWithNames[name] = true;
}
if (cb.__requireJsBuild) {
return cb.apply(null, args);
}
return undefined;
};
}());

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,10 +1,10 @@
/**
* @license RequireJS i18n Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license RequireJS i18n Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
/*jslint regexp: false, nomen: false, plusplus: false */
/*global require: false, navigator: false */
/*global require: false, navigator: false, define: false */
"use strict";
/**
@ -42,284 +42,101 @@
//nlsRegExp.exec("foo/bar/baz/nls/foo") gives:
//["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
//so, if match[5] is blank, it means this is the top bundle definition.
var nlsRegExp = /(^.*(^|\/)nls(\/|$))([^\/]*)\/?([^\/]*)/,
empty = {};
var nlsRegExp = /(^.*(^|\/)nls(\/|$))([^\/]*)\/?([^\/]*)/;
function getWaiting(name, context) {
var nlswAry = context.nlsWaiting;
return nlswAry[name] ||
//Push a new waiting object on the nlsWaiting array, but also put
//a shortcut lookup by name to the object on the array.
(nlswAry[name] = nlswAry[(nlswAry.push({ _name: name}) - 1)]);
}
/**
* Makes sure all the locale pieces are loaded, and finds the best match
* for the requested locale.
*/
function resolveLocale(masterName, bundle, locale, context) {
//Break apart the locale to get the parts.
var i, parts, toLoad, nlsw, loc, val, bestLoc = "root";
parts = locale.split("-");
//Now see what bundles exist for each country/locale.
//Want to walk up the chain, so if locale is en-us-foo,
//look for en-us-foo, en-us, en, then root.
toLoad = [];
nlsw = getWaiting(masterName, context);
for (i = parts.length; i > -1; i--) {
loc = i ? parts.slice(0, i).join("-") : "root";
val = bundle[loc];
if (val) {
//Store which bundle to use for the default bundle definition.
if (locale === context.config.locale && !nlsw._match) {
nlsw._match = loc;
}
//Store the best match for the target locale
if (bestLoc === "root") {
bestLoc = loc;
}
//Track that the locale needs to be resolved with its parts.
//Mark what locale should be used when resolving.
nlsw[loc] = loc;
//If locale value is true, it means it is a resource that
//needs to be loaded. Track it to load if it has not already
//been asked for.
if (val === true) {
//split off the bundl name from master name and insert the
//locale before the bundle name. So, if masterName is
//some/path/nls/colors, then the locale fr-fr's bundle name should
//be some/path/nls/fr-fr/colors
val = masterName.split("/");
val.splice(-1, 0, loc);
val = val.join("/");
if (!context.specified[val] && !(val in context.loaded) && !context.defined[val]) {
context.defPlugin[val] = 'i18n';
toLoad.push(val);
}
}
//Helper function to avoid repeating code. Lots of arguments in the
//desire to stay functional and support RequireJS contexts without having
//to know about the RequireJS contexts.
function addPart(locale, master, needed, toLoad, prefix, suffix) {
if (master[locale]) {
needed.push(locale);
if (master[locale] === true || master[locale] === 1) {
toLoad.push(prefix + locale + '/' + suffix);
}
}
//If locale was not an exact match, store the closest match for it.
if (bestLoc !== locale) {
if (context.defined[bestLoc]) {
//Already got it. Easy peasy lemon squeezy.
context.defined[locale] = context.defined[bestLoc];
} else {
//Need to wait for things to load then define it.
nlsw[locale] = bestLoc;
}
}
//Load any bundles that are still needed.
if (toLoad.length) {
require(toLoad, context.contextName);
}
}
require.plugin({
prefix: "i18n",
/**
* This callback is prefix-specific, only gets called for this prefix
*/
require: function (name, deps, callback, context) {
var i, match, nlsw, bundle, master, toLoad, obj = context.defined[name];
//All i18n modules must match the nls module name structure.
match = nlsRegExp.exec(name);
//If match[5] is blank, it means this is the top bundle definition,
//so it does not have to be handled. Only deal with ones that have a locale
//(a match[4] value but no match[5])
if (match[5]) {
master = match[1] + match[5];
//Track what locale bundle need to be generated once all the modules load.
nlsw = getWaiting(master, context);
nlsw[match[4]] = match[4];
bundle = context.nls[master];
if (!bundle) {
//No master bundle yet, ask for it.
context.defPlugin[master] = 'i18n';
require([master], context.contextName);
bundle = context.nls[master] = {};
}
//For nls modules, the callback is just a regular object,
//so save it off in the bundle now.
bundle[match[4]] = callback;
} else {
//Integrate bundle into the nls area.
bundle = context.nls[name];
if (bundle) {
//A specific locale already started the bundle object.
//Do a mixin (which will not overwrite the locale property
//on the bundle that has the previously loaded locale's info)
require.mixin(bundle, obj);
} else {
bundle = context.nls[name] = obj;
}
context.nlsRootLoaded[name] = true;
//Make sure there are no locales waiting to be resolved.
toLoad = context.nlsToLoad[name];
if (toLoad) {
delete context.nlsToLoad[name];
for (i = 0; i < toLoad.length; i++) {
resolveLocale(name, bundle, toLoad[i], context);
}
}
resolveLocale(name, bundle, context.config.locale, context);
}
},
/**
* Called when a new context is defined. Use this to store
* context-specific info on it.
*/
newContext: function (context) {
require.mixin(context, {
nlsWaiting: [],
nls: {},
nlsRootLoaded: {},
nlsToLoad: {}
});
if (!context.config.locale) {
context.config.locale = typeof navigator === "undefined" ? "root" :
(navigator.language || navigator.userLanguage || "root").toLowerCase();
}
},
function addIfExists(req, locale, toLoad, prefix, suffix) {
var fullName = prefix + locale + '/' + suffix;
if (require._fileExists(req.nameToUrl(fullName, null))) {
toLoad.push(fullName);
}
}
define({
/**
* Called when a dependency needs to be loaded.
*/
load: function (name, contextName) {
//Make sure the root bundle is loaded, to check if we can support
//loading the requested locale, or if a different one needs
//to be chosen.
var masterName, context = require.s.contexts[contextName], bundle,
match = nlsRegExp.exec(name), locale = match[4];
load: function (name, req, onLoad, config) {
config = config || {};
var masterName,
match = nlsRegExp.exec(name),
prefix = match[1],
locale = match[4],
suffix = match[5],
parts = locale.split("-"),
toLoad = [],
value = {},
i, part, current = "";
//If match[5] is blank, it means this is the top bundle definition,
//so it does not have to be handled. Only deal with ones that have a locale
//(a match[4] value but no match[5])
//so it does not have to be handled. Locale-specific requests
//will have a match[4] value but no match[5]
if (match[5]) {
//locale-specific bundle
masterName = match[1] + match[5];
bundle = context.nls[masterName];
if (context.nlsRootLoaded[masterName] && bundle) {
resolveLocale(masterName, bundle, locale, context);
} else {
//Store this locale to figure out after masterName is loaded and load masterName.
(context.nlsToLoad[masterName] || (context.nlsToLoad[masterName] = [])).push(locale);
context.defPlugin[masterName] = 'i18n';
require([masterName], contextName);
}
prefix = match[1];
masterName = prefix + suffix;
} else {
//Top-level bundle. Just call regular load, if not already loaded
if (!context.nlsRootLoaded[name]) {
context.defPlugin[name] = 'i18n';
require.load(name, contextName);
}
//Top-level bundle.
masterName = name;
suffix = match[4];
locale = config.locale || (config.locale =
typeof navigator === "undefined" ? "root" :
(navigator.language ||
navigator.userLanguage || "root").toLowerCase());
parts = locale.split("-");
}
},
/**
* Called when the dependencies of a module are checked.
*/
checkDeps: function (name, deps, context) {
//i18n bundles are always defined as objects for their "dependencies",
//and that object is already processed in the require method, no need to
//do work in here.
},
/**
* Called to determine if a module is waiting to load.
*/
isWaiting: function (context) {
return !!context.nlsWaiting.length;
},
/**
* Called when all modules have been loaded.
*/
orderDeps: function (context) {
//Clear up state since further processing could
//add more things to fetch.
var i, j, master, msWaiting, bundle, parts, moduleSuffix, mixed,
modulePrefix, loc, defLoc, locPart, nlsWaiting = context.nlsWaiting,
bestFit;
context.nlsWaiting = [];
context.nlsToLoad = {};
//First, properly mix in any nls bundles waiting to happen.
for (i = 0; (msWaiting = nlsWaiting[i]); i++) {
//Each property is a master bundle name.
master = msWaiting._name;
bundle = context.nls[master];
defLoc = null;
//Create the module name parts from the master name. So, if master
//is foo/nls/bar, then the parts should be prefix: "foo/nls",
// suffix: "bar", and the final locale's module name will be foo/nls/locale/bar
parts = master.split("/");
modulePrefix = parts.slice(0, parts.length - 1).join("/");
moduleSuffix = parts[parts.length - 1];
//Cycle through the locale props on the waiting object and combine
//the locales together.
for (loc in msWaiting) {
if (loc !== "_name" && !(loc in empty)) {
if (loc === "_match") {
//Found default locale to use for the top-level bundle name.
defLoc = msWaiting[loc];
} else if (msWaiting[loc] !== loc) {
//A "best fit" locale, store it off to the end and handle
//it at the end by just assigning the best fit value, since
//after this for loop, the best fit locale will be defined.
(bestFit || (bestFit = {}))[loc] = msWaiting[loc];
} else {
//Mix in the properties of this locale together.
//Split the locale into pieces.
mixed = {};
parts = loc.split("-");
for (j = parts.length; j > 0; j--) {
locPart = parts.slice(0, j).join("-");
if (locPart !== "root" && bundle[locPart]) {
require.mixin(mixed, bundle[locPart]);
}
}
if (bundle.root) {
require.mixin(mixed, bundle.root);
}
context.defined[modulePrefix + "/" + loc + "/" + moduleSuffix] = mixed;
}
}
if (config.isBuild) {
//Check for existence of all locale possible files and
//require them if exist.
toLoad.push(masterName);
addIfExists(req, "root", toLoad, prefix, suffix);
for (i = 0; (part = parts[i]); i++) {
current += (current ? "-" : "") + part;
addIfExists(req, current, toLoad, prefix, suffix);
}
req(toLoad);
onLoad();
} else {
//First, fetch the master bundle, it knows what locales are available.
req([masterName], function (master) {
//Figure out the best fit
var needed = [];
//Finally define the default locale. Wait to the end of the property
//loop above so that the default locale bundle has been properly mixed
//together.
context.defined[master] = context.defined[modulePrefix + "/" + defLoc + "/" + moduleSuffix];
//Handle any best fit locale definitions.
if (bestFit) {
for (loc in bestFit) {
if (!(loc in empty)) {
context.defined[modulePrefix + "/" + loc + "/" + moduleSuffix] = context.defined[modulePrefix + "/" + bestFit[loc] + "/" + moduleSuffix];
}
//Always allow for root, then do the rest of the locale parts.
addPart("root", master, needed, toLoad, prefix, suffix);
for (i = 0; (part = parts[i]); i++) {
current += (current ? "-" : "") + part;
addPart(current, master, needed, toLoad, prefix, suffix);
}
}
//Load all the parts missing.
req(toLoad, function () {
var i, partBundle;
for (i = needed.length - 1; i > -1 && (part = needed[i]); i--) {
partBundle = master[part];
if (partBundle === true || partBundle === 1) {
partBundle = req(prefix + part + '/' + suffix);
}
require.mixin(value, partBundle);
}
//All done, notify the loader.
onLoad(value);
});
});
}
}
});

Просмотреть файл

@ -1,123 +0,0 @@
/**
* @license RequireJS jsonp Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
/*jslint nomen: false, plusplus: false */
/*global require: false, setTimeout: false */
"use strict";
(function () {
var countId = 0;
//A place to hold callback functions
require._jsonp = {};
require.plugin({
prefix: "jsonp",
/**
* This callback is prefix-specific, only gets called for this prefix
*/
require: function (name, deps, callback, context) {
//No-op, require never gets these jsonp items, they are always
//a dependency, see load for the action.
},
/**
* Called when a new context is defined. Use this to store
* context-specific info on it.
*/
newContext: function (context) {
require.mixin(context, {
jsonpWaiting: []
});
},
/**
* Called when a dependency needs to be loaded.
*/
load: function (name, contextName) {
//Name has format: some/url?param1=value1&callback=?
//where the last question mark indicates where the jsonp callback
//function name needs to go.
var index = name.indexOf("?"),
url = name.substring(0, index),
params = name.substring(index + 1, name.length),
context = require.s.contexts[contextName],
data = {
name: name
},
funcName = "f" + (countId++),
head = require.s.head,
node = head.ownerDocument.createElement("script");
//Create JSONP callback function
require._jsonp[funcName] = function (value) {
data.value = value;
context.loaded[name] = true;
require.checkLoaded(contextName);
//Use a setTimeout for cleanup because some older IE versions vomit
//if removing a script node while it is being evaluated.
setTimeout(function () {
head.removeChild(node);
delete require._jsonp[funcName];
}, 15);
};
//Hold on to the data for later dependency resolution in orderDeps.
context.jsonpWaiting.push(data);
//Build up the full JSONP URL
url = require.nameToUrl(url, "?", contextName);
//nameToUrl call may or may not have placed an ending ? on the URL,
//be sure there is one and add the rest of the params.
url += (url.indexOf("?") === -1 ? "?" : "") + params.replace("?", "require._jsonp." + funcName);
context.loaded[name] = false;
node.type = "text/javascript";
node.charset = "utf-8";
node.src = url;
//Use async so Gecko does not block on executing the script if something
//like a long-polling comet tag is being run first. Gecko likes
//to evaluate scripts in DOM order, even for dynamic scripts.
//It will fetch them async, but only evaluate the contents in DOM
//order, so a long-polling script tag can delay execution of scripts
//after it. But telling Gecko we expect async gets us the behavior
//we want -- execute it whenever it is finished downloading. Only
//Helps Firefox 3.6+
node.async = true;
head.appendChild(node);
},
/**
* Called when the dependencies of a module are checked.
*/
checkDeps: function (name, deps, context) {
//No-op, checkDeps never gets these jsonp items, they are always
//a dependency, see load for the action.
},
/**
* Called to determine if a module is waiting to load.
*/
isWaiting: function (context) {
return !!context.jsonpWaiting.length;
},
/**
* Called when all modules have been loaded.
*/
orderDeps: function (context) {
//Clear up state since further processing could
//add more things to fetch.
var i, dep, waitAry = context.jsonpWaiting;
context.jsonpWaiting = [];
for (i = 0; (dep = waitAry[i]); i++) {
context.defined[dep.name] = dep.value;
}
}
});
}());

Просмотреть файл

@ -1,10 +1,11 @@
/**
* @license RequireJS order Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license RequireJS order Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
/*jslint nomen: false, plusplus: false */
/*global require: false, window: false, document: false, setTimeout: false */
/*global require: false, define: false, window: false, document: false,
setTimeout: false */
"use strict";
(function () {
@ -14,39 +15,65 @@
//Currently, Gecko and Opera do not load/fire onload for scripts with
//type="script/cache" but they execute injected scripts in order
//unless the 'async' flag is present.
var supportsInOrderExecution = ((window.opera && Object.prototype.toString.call(window.opera) === "[object Opera]") ||
//However, this is all changing in latest browsers implementing HTML5
//spec. Firefox nightly supports using the .async true by default, and
//if false, then it will execute in order. Favor that test first for forward
//compatibility. However, it is unclear if webkit/IE will follow suit.
//Latest webkit breaks the script/cache trick.
//Test for document and window so that this file can be loaded in
//a web worker/non-browser env. It will not make sense to use this
//plugin in a non-browser env, but the file should not error out if included
//in the allplugins-require.js file, then loaded in a non-browser env.
var supportsInOrderExecution = typeof document !== "undefined" &&
typeof window !== "undefined" &&
(document.createElement("script").async ||
(window.opera && Object.prototype.toString.call(window.opera) === "[object Opera]") ||
//If Firefox 2 does not have to be supported, then
//a better check may be:
//('mozIsLocallyAvailable' in window.navigator)
("MozAppearance" in document.documentElement.style)),
readyRegExp = /^(complete|loaded)$/;
readyRegExp = /^(complete|loaded)$/,
waiting = [],
cached = {};
function loadResource(name, req, onLoad) {
req([name], function (value) {
//The value may be a real defined module. Wrap
//it in a function call, because this function is used
//as the factory function for this ordered dependency.
onLoad(function () {
return value;
});
});
}
//Callback used by the type="script/cache" callback that indicates a script
//has finished downloading.
function scriptCacheCallback(evt) {
var node = evt.currentTarget || evt.srcElement, i,
context, contextName, moduleName, waiting, cached;
moduleName, resource;
if (evt.type === "load" || readyRegExp.test(node.readyState)) {
//Pull out the name of the module and the context.
contextName = node.getAttribute("data-requirecontext");
moduleName = node.getAttribute("data-requiremodule");
context = require.s.contexts[contextName];
waiting = context.orderWaiting;
cached = context.orderCached;
//Mark this cache request as loaded
cached[moduleName] = true;
//Find out how many ordered modules have loaded
for (i = 0; cached[waiting[i]]; i++) {}
if (i > 0) {
require(waiting.splice(0, i), contextName);
for (i = 0; (resource = waiting[i]); i++) {
if (cached[resource.name]) {
loadResource(resource.name, resource.req, resource.onLoad);
} else {
//Something in the ordered list is not loaded,
//so wait.
break;
}
}
//If no other order cache items are in the queue, do some cleanup.
if (!waiting.length) {
context.orderCached = {};
//If just loaded some items, remove them from waiting.
if (i > 0) {
waiting.splice(0, i);
}
//Remove this script tag from the DOM
@ -58,34 +85,15 @@
}
}
require.plugin({
prefix: "order",
define({
load: function (name, req, onLoad, config) {
var url = req.nameToUrl(name, null);
/**
* This callback is prefix-specific, only gets called for this prefix
*/
require: function (name, deps, callback, context) {
//No-op, require never gets these order items, they are always
//a dependency, see load for the action.
},
/**
* Called when a new context is defined. Use this to store
* context-specific info on it.
*/
newContext: function (context) {
require.mixin(context, {
orderWaiting: [],
orderCached: {}
});
},
/**
* Called when a dependency needs to be loaded.
*/
load: function (name, contextName) {
var context = require.s.contexts[contextName],
url = require.nameToUrl(name, null, contextName);
//If a build, just load the module as usual.
if (config.isBuild) {
loadResource(name, req, onLoad);
return;
}
//Make sure the async attribute is not set for any pathway involving
//this script.
@ -93,7 +101,14 @@
if (supportsInOrderExecution) {
//Just a normal script tag append, but without async attribute
//on the script.
require([name], contextName);
req([name], function (value) {
//The value may be a real defined module. Wrap
//it in a function call, because this function is used
//as the factory function for this ordered dependency.
onLoad(function () {
return value;
});
});
} else {
//Credit to LABjs author Kyle Simpson for finding that scripts
//with type="script/cache" allow scripts to be downloaded into
@ -101,32 +116,24 @@
//so that subsequent addition of a real type="text/javascript"
//tag will cause the scripts to be executed immediately in the
//correct order.
context.orderWaiting.push(name);
context.loaded[name] = false;
require.attach(url, contextName, name, scriptCacheCallback, "script/cache");
if (req.isDefined(name)) {
req([name], function (value) {
//The value may be a real defined module. Wrap
//it in a function call, because this function is used
//as the factory function for this ordered dependency.
onLoad(function () {
return value;
});
});
} else {
waiting.push({
name: name,
req: req,
onLoad: onLoad
});
require.attach(url, "", name, scriptCacheCallback, "script/cache");
}
}
},
/**
* Called when the dependencies of a module are checked.
*/
checkDeps: function (name, deps, context) {
//No-op, checkDeps never gets these order items, they are always
//a dependency, see load for the action.
},
/**
* Called to determine if a module is waiting to load.
*/
isWaiting: function (context) {
return !!context.orderWaiting.length;
},
/**
* Called when all modules have been loaded. Not needed for this plugin.
* State is reset as part of scriptCacheCallback.
*/
orderDeps: function (context) {
}
});
}());

Просмотреть файл

@ -1,6 +1,6 @@
/**
* @license RequireJS rhino Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
/*global require: false, readFile: false */
@ -10,21 +10,69 @@ TODO: Work out relative paths, that use ./ and such, and allow loading normal
CommonJS modules, by overriding require.get().
*/
/*globals load: false */
/*globals load: false, java: false */
"use strict";
require.load = function (moduleName, contextName) {
var url = require.nameToUrl(moduleName, null, contextName),
context = require.s.contexts[contextName];
(function () {
//isDone is used by require.ready()
require.s.isDone = false;
var fileUtil = {
backSlashRegExp: /\\/g,
//Indicate a the module is in process of loading.
context.loaded[moduleName] = false;
getLineSeparator: function () {
return java.lang.System.getProperty("line.separator"); //Java String
}
};
load(url);
require.load = function (context, moduleName, url) {
//isDone is used by require.ready()
require.s.isDone = false;
//Support anonymous modules.
require.completeLoad(moduleName, context);
};
//Indicate a the module is in process of loading.
context.loaded[moduleName] = false;
context.scriptCount += 1;
load(url);
//Support anonymous modules.
context.completeLoad(moduleName);
};
//Adapter to get text plugin to work.
require.fetchText = function (url, callback) {
var encoding = "utf-8",
file = new java.io.File(url),
lineSeparator = fileUtil.getLineSeparator(),
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
stringBuffer, line,
content = '';
try {
stringBuffer = new java.lang.StringBuffer();
line = input.readLine();
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
// http://www.unicode.org/faq/utf_bom.html
// Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
if (line && line.length() && line.charAt(0) === 0xfeff) {
// Eat the BOM, since we've already found the encoding on this file,
// and we plan to concatenating this buffer with others; the BOM should
// only appear at the top of a file.
line = line.substring(1);
}
stringBuffer.append(line);
while ((line = input.readLine()) !== null) {
stringBuffer.append(lineSeparator);
stringBuffer.append(line);
}
//Make sure we return a JavaScript string and not a Java string.
content = String(stringBuffer.toString()); //String
} finally {
input.close();
}
callback(content);
};
}());

Просмотреть файл

@ -1,16 +1,18 @@
/**
* @license RequireJS text Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* @license RequireJS text Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
/*jslint regexp: false, nomen: false, plusplus: false */
/*global require: false, XMLHttpRequest: false, ActiveXObject: false */
/*global require: false, XMLHttpRequest: false, ActiveXObject: false,
define: false */
"use strict";
(function () {
var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im;
bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
buildMap = [];
if (!require.textStrip) {
require.textStrip = function (text) {
@ -30,6 +32,17 @@
};
}
if (!require.jsEscape) {
require.jsEscape = function (text) {
return text.replace(/(['\\])/g, '\\$1')
.replace(/[\f]/g, "\\f")
.replace(/[\b]/g, "\\b")
.replace(/[\n]/g, "\\n")
.replace(/[\t]/g, "\\t")
.replace(/[\r]/g, "\\r");
};
}
//Upgrade require to add some methods for XHR handling. But it could be that
//this require is used in a non-browser env, so detect for existing method
//before attaching one.
@ -50,7 +63,7 @@
progIds = [progId]; // so faster next time
break;
}
}
}
}
if (!xhr) {
@ -60,7 +73,7 @@
return xhr;
};
}
if (!require.fetchText) {
require.fetchText = function (url, callback) {
var xhr = require.getXhr();
@ -76,120 +89,43 @@
};
}
require.plugin({
prefix: "text",
/**
* This callback is prefix-specific, only gets called for this prefix
*/
require: function (name, deps, callback, context) {
//No-op, require never gets these text items, they are always
//a dependency, see load for the action.
},
/**
* Called when a new context is defined. Use this to store
* context-specific info on it.
*/
newContext: function (context) {
require.mixin(context, {
text: {},
textWaiting: []
});
},
/**
* Called when a dependency needs to be loaded.
*/
load: function (name, contextName) {
//Name has format: some.module!filext!strip!text
//The strip and text parts are optional.
define({
load: function (name, req, onLoad, config) {
//Name has format: some.module.filext!strip
//The strip part is optional.
//if strip is present, then that means only get the string contents
//inside a body tag in an HTML string. For XML/SVG content it means
//removing the <?xml ...?> declarations so the content can be inserted
//into the current doc without problems.
//If text is present, it is the actual text of the file.
var strip = false, text = null, key, url, index = name.indexOf("."),
modName = name.substring(0, index), fullKey,
ext = name.substring(index + 1, name.length),
context = require.s.contexts[contextName],
tWaitAry = context.textWaiting;
var strip = false, url, index = name.indexOf("."),
modName = name.substring(0, index),
ext = name.substring(index + 1, name.length);
index = ext.indexOf("!");
if (index !== -1) {
//Pull off the strip arg.
strip = ext.substring(index + 1, ext.length);
strip = strip === "strip";
ext = ext.substring(0, index);
index = strip.indexOf("!");
if (index !== -1 && strip.substring(0, index) === "strip") {
//Pull off the text.
text = strip.substring(index + 1, strip.length);
strip = "strip";
} else if (strip !== "strip") {
//strip is actually the inlined text.
text = strip;
strip = null;
}
//Load the text.
url = req.nameToUrl(modName, "." + ext);
require.fetchText(url, function (text) {
text = strip ? require.textStrip(text) : text;
if (config.isBuild && config.inlineText) {
buildMap[name] = text;
}
}
key = modName + "!" + ext;
fullKey = strip ? key + "!" + strip : key;
//Store off text if it is available for the given key and be done.
if (text !== null && !context.text[key]) {
context.defined[name] = context.text[key] = text;
return;
}
//If text is not available, load it.
if (!context.text[key] && !context.textWaiting[key] && !context.textWaiting[fullKey]) {
//Keep track that the fullKey needs to be resolved, during the
//orderDeps stage.
if (!tWaitAry[fullKey]) {
tWaitAry[fullKey] = tWaitAry[(tWaitAry.push({
name: name,
key: key,
fullKey: fullKey,
strip: !!strip
}) - 1)];
}
//Load the text.
url = require.nameToUrl(modName, "." + ext, contextName);
context.loaded[name] = false;
require.fetchText(url, function (text) {
context.text[key] = text;
context.loaded[name] = true;
require.checkLoaded(contextName);
});
}
onLoad(text);
});
},
/**
* Called when the dependencies of a module are checked.
*/
checkDeps: function (name, deps, context) {
//No-op, checkDeps never gets these text items, they are always
//a dependency, see load for the action.
},
/**
* Called to determine if a module is waiting to load.
*/
isWaiting: function (context) {
return !!context.textWaiting.length;
},
/**
* Called when all modules have been loaded.
*/
orderDeps: function (context) {
//Clear up state since further processing could
//add more things to fetch.
var i, dep, text, tWaitAry = context.textWaiting;
context.textWaiting = [];
for (i = 0; (dep = tWaitAry[i]); i++) {
text = context.text[dep.key];
context.defined[dep.name] = dep.strip ? require.textStrip(text) : text;
write: function (pluginName, moduleName, write) {
if (moduleName in buildMap) {
var text = require.jsEscape(buildMap[moduleName]);
write("define('" + pluginName + "!" + moduleName +
"', function () { return '" + text + "';});\n");
}
}
});

Просмотреть файл

@ -1,30 +0,0 @@
/**
* @license RequireJS transportD Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* see: http://github.com/jrburke/requirejs for details
*/
/*jslint */
/*global require: false */
"use strict";
/**
* An adapter for the CommonJS Transport/D proposal:
* http://wiki.commonjs.org/wiki/Modules/Transport/D
* NOTE: this integration does NOT support contexts, so only one version in the page.
* @param {Object} modules a dictionary of module names with module descriptors
* @param [Array] dependencies a list of module names that are dependencies for
* all the modules listed in the modules argument.
*/
require.define = function (modules, dependencies) {
var moduleName, descriptor;
for (moduleName in modules) {
if (modules.hasOwnProperty(moduleName)) {
descriptor = modules[moduleName];
require.def(
moduleName,
(descriptor.injects || ["require", "exports", "module"]).concat(dependencies || []),
typeof descriptor === "function" ? descriptor : descriptor.factory
);
}
}
};

Просмотреть файл

@ -1,10 +0,0 @@
{
baseUrl: "../../web-static/scripts/",
paths: {
"index": "../settings/index",
"jquery": "requireplugins-jquery-1.4.2"
},
name: "index",
exclude: ['jquery'],
out: '../../web-static/settings/index.js'
}

Просмотреть файл

@ -1,10 +0,0 @@
{
baseUrl: "../../web-static/scripts/",
paths: {
"index": "../share/index",
"jquery": "requireplugins-jquery-1.4.2"
},
name: "index",
exclude: ['jquery'],
out: '../../web-static/share/index.js'
}

304
web/0.1.7/auth.html Normal file
Просмотреть файл

@ -0,0 +1,304 @@
<!DOCTYPE html>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Raindrop.
-
- The Initial Developer of the Original Code is
- Mozilla Messaging, Inc..
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- -->
<html>
<head>
<title>Firefox Share OAuthorization</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<script src="/0.1.7/scripts/requireplugins-jquery.js" charset="utf-8"></script>
<style>
html, body {
background-color: #fff;
height: 100%;
color: #0A0A0A;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 21px;
overflow: hidden;
}
.connecting {
margin-top: 60px;
text-align: center;
}
.connecting img {
vertical-align: middle;
}
.hidden {
display: none;
}
.invisible {
visibility: hidden;
}
#oauth {
background-color: #fff;
width: 100%;
position: absolute;
top: 50%;
left: 50%;
margin-left: -150px;
margin-top: -95px;
width: 300px;
background-image: url("/0.1.7/i/f1Logo.png");
background-position: center top;
background-repeat: no-repeat;
padding: 100px 0 0 0;
}
#oauth .text {
display: block;
margin: 0 0 7px 0;
}
#oauth .subtext {
margin-left: 7px;
color: #666666;
font-family: "Lucida Grande", Verdana, sans-serif;
font-size: 12px;
}
.controls {
width: 300px;
}
button {
height: 30px;
border-width: 1px 1px 1px 0;
border-style: solid;
border-color: #888;
cursor: pointer;
padding: 0 10px;
-moz-border-radius: 0 2px 2px 0;
-webkit-border-radius: 0 2px 2px 0;
border-radius: 0 2px 2px 0;
background-image: -moz-linear-gradient(center top , #fafafa 0%, #ddd 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fafafa), color-stop(100%, #ddd));
}
button:active {
-moz-box-shadow: 0 0 1px #666666 inset;
-webkit-box-shadow: 0 0 1px #666666 inset;
box-shadow: 0 0 1px #666666 inset;
background-image: -moz-linear-gradient(center top , #eee 0%, #ccc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eee), color-stop(100%, #ccc));
}
input {
border-width: 1px;
border-style: solid;
border-color: #888;
font-family: "Lucida Grande", Verdana, sans-serif;
font-size: 12px;
line-height: 18px;
padding: 3px;
margin: 0;
-moz-border-radius: 2px 0 0 2px;
-moz-box-shadow:0 3px 3px -3px rgba(0, 0, 0, 0.25) inset, 0 1px 0 #fff;
}
input:focus {
-moz-box-shadow: 0 0 0 3px rgba(0, 162, 255, 0.25) inset, 0 1px 0 #fff;
}
input.google {
background-image: url("/0.1.7/i/sprite.png");
background-position: 5px -159px;
background-repeat: no-repeat;
padding: 0 0 0 26px;
}
.hbox {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
display: box;
box-orient: horizontal;
box-align: stretch;
}
.hbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.vbox {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-align: stretch;
display: box;
box-orient: vertical;
box-align: stretch;
}
.vbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.spacer {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.reverse {
-webkit-box-direction: reverse;
-moz-box-direction: reverse;
box-direction: reverse;
}
.boxFlex0 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
}
.boxFlex1, .boxFlex {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.boxFlex2 {
-webkit-box-flex: 2;
-moz-box-flex: 2;
box-flex: 2;
}
.boxGroup1 {
-webkit-box-flex-group: 1;
-moz-box-flex-group: 1;
box-flex-group: 1;
}
.boxGroup2 {
-webkit-box-flex-group: 2;
-moz-box-flex-group: 2;
box-flex-group: 2;
}
.start {
-webkit-box-pack: start;
-moz-box-pack: start;
box-pack: start;
}
.end {
-webkit-box-pack: end;
-moz-box-pack: end;
box-pack: end;
}
.center {
-webkit-box-pack: center;
-moz-box-pack: center;
box-pack: center;
}
</style>
<script>
require(["require", "jquery", "blade/url"],
function (require, $, url) {
var target = window.location.href.split('#')[1];
if (target && (target === 'oauth_success' || target === 'oauth_failure')) {
//TODO: ideally lock down the domain be location.hostname, but
//a problem for 127 addresses?
// XXX hacky way to handle fennec, since we didn't open a window,
// catch the exception when using window.opener and redirect
try {
window.opener.postMessage(target, '*');
window.close();
} catch(e) {
var url = location.protocol + "//" + location.host + "/settings/?target="+target;
window.location = url;
}
}
var search = window.location.href.split('?')[1];
if (search) {
search = search.split('#')[0];
var args = url.queryToObject(search);
if (args['domain']) {
$("#domain").attr("value", args['domain']);
if (args['domain'] == 'googleapps.com') {
$('#oauth').removeClass('hidden');
$('#message').addClass('hidden');
$('#submitbtn').click(function (evt) {
$('#oauth').addClass('hidden');
$('#message').removeClass('hidden');
document.authForm.submit();
});
} else {
document.authForm.submit();
}
}
}
});
</script>
</head>
<body class="settings">
<div id="oauth" class="authorize hidden">
<form name="authForm" action="/api/account/authorize" method="POST">
<input type="hidden" name="domain" id="domain" value="">
<span class="text">Enter your Google Apps domain</span>
<div class="controls hbox">
<input class="boxFlex google" name="openid_identifier" id="openid_identifier" value="">
<input class="boxFlex google" type="hidden" name="end_point_success" value="/auth.html#oauth_success">
<input class="boxFlex google" type="hidden" name="end_point_auth_failure" value="/auth.html#oauth_failure">
<button id='submitbtn' type="submit">submit</button>
</div>
<span class="subtext">ex: yourappdomain.com</span>
</form>
</div>
<div style="clear: both"/>
</div>
<div id='message' class="connecting"><img src="i/loader-w.gif"> connecting...</div>
</body>
</html>

Просмотреть файл

10
web/0.1.7/build.js Normal file
Просмотреть файл

@ -0,0 +1,10 @@
({
baseUrl: "scripts/",
paths: {
"index": "../index",
"jquery": "requireplugins-jquery"
},
name: "index",
exclude: ['jquery'],
out: './index.js'
})

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 1.1 KiB

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 469 B

После

Ширина:  |  Высота:  |  Размер: 469 B

Двоичные данные
web/0.1.7/i/LinkedIn_Logo16px.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 716 B

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 670 B

После

Ширина:  |  Высота:  |  Размер: 670 B

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 494 B

После

Ширина:  |  Высота:  |  Размер: 494 B

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 142 B

После

Ширина:  |  Высота:  |  Размер: 142 B

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 139 B

После

Ширина:  |  Высота:  |  Размер: 139 B

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 136 B

После

Ширина:  |  Высота:  |  Размер: 136 B

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 139 B

После

Ширина:  |  Высота:  |  Размер: 139 B

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 389 B

После

Ширина:  |  Высота:  |  Размер: 389 B

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 4.7 KiB

После

Ширина:  |  Высота:  |  Размер: 4.7 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 4.4 KiB

После

Ширина:  |  Высота:  |  Размер: 4.4 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 448 B

После

Ширина:  |  Высота:  |  Размер: 448 B

Двоичные данные
web/0.1.7/i/fancybox/blank.gif Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 43 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_close.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Двоичные данные
web/0.1.7/i/fancybox/fancy_loading.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 10 KiB

Двоичные данные
web/0.1.7/i/fancybox/fancy_nav_left.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
web/0.1.7/i/fancybox/fancy_nav_right.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
web/0.1.7/i/fancybox/fancy_shadow_e.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 107 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_shadow_n.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 106 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_shadow_ne.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 347 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_shadow_nw.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 324 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_shadow_s.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 111 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_shadow_se.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 352 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_shadow_sw.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 340 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_shadow_w.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 103 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_title_left.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 503 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_title_main.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 96 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_title_over.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 70 B

Двоичные данные
web/0.1.7/i/fancybox/fancy_title_right.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 506 B

Двоичные данные
web/0.1.7/i/fancybox/fancybox-x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 203 B

Двоичные данные
web/0.1.7/i/fancybox/fancybox-y.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 176 B

Двоичные данные
web/0.1.7/i/fancybox/fancybox.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 15 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 468 B

После

Ширина:  |  Высота:  |  Размер: 468 B

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 2.7 KiB

После

Ширина:  |  Высота:  |  Размер: 2.7 KiB

Двоичные данные
web/0.1.7/i/panel/f1accounts.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 67 KiB

Двоичные данные
web/0.1.7/i/panel/f1panel.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 66 KiB

Двоичные данные
web/0.1.7/i/panel/step-01.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичные данные
web/0.1.7/i/panel/step-02.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 27 KiB

Двоичные данные
web/0.1.7/i/panel/step-022.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 23 KiB

Двоичные данные
web/0.1.7/i/panel/step-03.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.2 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 27 KiB

После

Ширина:  |  Высота:  |  Размер: 27 KiB

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше