Merge branch 'develop' into feature/metrics
32
Makefile
|
@ -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;
|
||||
}
|
||||
|
|
Двоичные данные
extensions/firefox-share/src/chrome/skin/minefield-win/toolbar-button-glow.png
Normal file
После Ширина: | Высота: | Размер: 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 */
|
||||
|
|
Двоичные данные
extensions/firefox-share/src/chrome/skin/minefield/toolbar-button-glow.png
Normal file
После Ширина: | Высота: | Размер: 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;
|
||||
}
|
||||
|
|
После Ширина: | Высота: | Размер: 22 KiB |
Двоичные данные
extensions/firefox-share/src/chrome/skin/toolbar-button.png
До Ширина: | Высота: | Размер: 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
|
||||
|
|
|
@ -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 — <span style="color:#666;">"share links with the people that matter to you"</span>
|
||||
|
|
5
setup.py
|
@ -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 @@
|
|||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
})
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
}
|
|
@ -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>
|
|
@ -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 |
После Ширина: | Высота: | Размер: 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 |
После Ширина: | Высота: | Размер: 43 B |
После Ширина: | Высота: | Размер: 1.5 KiB |
После Ширина: | Высота: | Размер: 10 KiB |
После Ширина: | Высота: | Размер: 1.4 KiB |
После Ширина: | Высота: | Размер: 1.4 KiB |
После Ширина: | Высота: | Размер: 107 B |
После Ширина: | Высота: | Размер: 106 B |
После Ширина: | Высота: | Размер: 347 B |
После Ширина: | Высота: | Размер: 324 B |
После Ширина: | Высота: | Размер: 111 B |
После Ширина: | Высота: | Размер: 352 B |
После Ширина: | Высота: | Размер: 340 B |
После Ширина: | Высота: | Размер: 103 B |
После Ширина: | Высота: | Размер: 503 B |
После Ширина: | Высота: | Размер: 96 B |
После Ширина: | Высота: | Размер: 70 B |
После Ширина: | Высота: | Размер: 506 B |
После Ширина: | Высота: | Размер: 203 B |
После Ширина: | Высота: | Размер: 176 B |
После Ширина: | Высота: | Размер: 15 KiB |
До Ширина: | Высота: | Размер: 468 B После Ширина: | Высота: | Размер: 468 B |
До Ширина: | Высота: | Размер: 2.7 KiB После Ширина: | Высота: | Размер: 2.7 KiB |
После Ширина: | Высота: | Размер: 67 KiB |
После Ширина: | Высота: | Размер: 66 KiB |
После Ширина: | Высота: | Размер: 12 KiB |
После Ширина: | Высота: | Размер: 27 KiB |
После Ширина: | Высота: | Размер: 23 KiB |
После Ширина: | Высота: | Размер: 5.2 KiB |
До Ширина: | Высота: | Размер: 27 KiB После Ширина: | Высота: | Размер: 27 KiB |