Merge branch 'develop' into feature/metrics
32
Makefile
|
@ -1,27 +1,17 @@
|
||||||
|
version := 0.1.8
|
||||||
ifeq ($(TOPSRCDIR),)
|
ifeq ($(TOPSRCDIR),)
|
||||||
export TOPSRCDIR = $(shell pwd)
|
export TOPSRCDIR = $(shell pwd)
|
||||||
endif
|
endif
|
||||||
srcdir=$(TOPSRCDIR)/extensions/firefox-share/src/
|
srcdir=$(TOPSRCDIR)/extensions/firefox-share/src/
|
||||||
objdir=$(TOPSRCDIR)/extensions/firefox-share/dist/
|
objdir=$(TOPSRCDIR)/extensions/firefox-share/dist/
|
||||||
stage_dir=$(objdir)/stage
|
stage_dir=$(objdir)/stage
|
||||||
xpi_dir=$(TOPSRCDIR)/web
|
xpi_dir=$(TOPSRCDIR)/web/dev
|
||||||
web_dir=$(TOPSRCDIR)/web
|
web_dir=$(TOPSRCDIR)/web/dev
|
||||||
static_dir=$(TOPSRCDIR)/web-static
|
static_dir=$(TOPSRCDIR)/web/$(version)
|
||||||
webbuild_dir=$(TOPSRCDIR)/tools/webbuild
|
webbuild_dir=$(TOPSRCDIR)/tools/webbuild
|
||||||
requirejs_dir=$(webbuild_dir)/requirejs
|
requirejs_dir=$(webbuild_dir)/requirejs
|
||||||
|
|
||||||
version := 0.7.3
|
xpi_name := ffshare.xpi
|
||||||
|
|
||||||
ifeq ($(release_build),)
|
|
||||||
xpi_type := dev
|
|
||||||
update_url :=
|
|
||||||
else
|
|
||||||
xpi_type := rel
|
|
||||||
update_url :=
|
|
||||||
endif
|
|
||||||
|
|
||||||
xpi_name := share-$(version)-$(xpi_type).xpi
|
|
||||||
xpi_files := chrome.manifest chrome install.rdf defaults components modules
|
xpi_files := chrome.manifest chrome install.rdf defaults components modules
|
||||||
dep_files := Makefile $(shell find $(srcdir) -type f)
|
dep_files := Makefile $(shell find $(srcdir) -type f)
|
||||||
|
|
||||||
|
@ -71,10 +61,16 @@ web: $(static_dir)
|
||||||
|
|
||||||
$(static_dir):
|
$(static_dir):
|
||||||
rsync -av $(web_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:
|
clean:
|
||||||
rm -rf $(objdir)
|
rm -rf $(objdir)
|
||||||
rm -rf $(static_dir)
|
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
|
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
|
## 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.
|
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.
|
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.
|
# below for this server.
|
||||||
oauth.facebook.com.app_id = 163981616966631
|
oauth.facebook.com.app_id = 163981616966631
|
||||||
oauth.facebook.com.app_secret = 78e3bd4ab991ccf50fb9220452eb30b4
|
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.authorize = https://graph.facebook.com/oauth/authorize
|
||||||
oauth.facebook.com.access = https://graph.facebook.com/oauth/access_token
|
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
|
# also set verified = 1
|
||||||
oauth.yahoo.com.consumer_key = dj0yJmk9TjFpSlVBcmY2Q2pnJmQ9WVdrOWQwUjVVVFJKTkdVbWNHbzlNVEF6TnpZME1ERTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD1hZg--
|
oauth.yahoo.com.consumer_key = dj0yJmk9TjFpSlVBcmY2Q2pnJmQ9WVdrOWQwUjVVVFJKTkdVbWNHbzlNVEF6TnpZME1ERTJNZy0tJnM9Y29uc3VtZXJzZWNyZXQmeD1hZg--
|
||||||
oauth.yahoo.com.consumer_secret = a47367578f07e3ea1ddb045b3003a9c7d95a5f69
|
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
|
# set to true if you have completed domain verification with Yahoo
|
||||||
oauth.yahoo.com.verified = 1
|
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]
|
[server:main]
|
||||||
use = egg:Paste#http
|
use = egg:Paste#http
|
||||||
host = 127.0.0.1
|
host = 127.0.0.1
|
||||||
|
@ -89,7 +95,7 @@ use = egg:Paste#urlmap
|
||||||
/api = api
|
/api = api
|
||||||
|
|
||||||
[app:home]
|
[app:home]
|
||||||
use = egg:Paste#static
|
use = egg:linkdrop#static
|
||||||
document_root = %(here)s/web
|
document_root = %(here)s/web
|
||||||
|
|
||||||
[app:api]
|
[app:api]
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>F1 not available</title>
|
<title>F1 not available</title>
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -40,59 +41,57 @@
|
||||||
font-style: inherit;
|
font-style: inherit;
|
||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
|
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-family: "Lucida Grande", Verdana, sans-serif;
|
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 {
|
div.status {
|
||||||
min-height: 113px;
|
width: 400px;
|
||||||
padding: 0 10px;
|
height: 180px;
|
||||||
overflow: hidden;
|
|
||||||
border-bottom: 1px solid #777;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.status {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 113px;
|
|
||||||
line-height: 113px;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
color: #0a0a0a;
|
color: #0a0a0a;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.status.intermediate.error {
|
div.status.intermediate.error {
|
||||||
background-color: rgba(255,115,0,0.75);
|
background-color: rgba(255,115,0,0.75);
|
||||||
color: #FFFFFF;
|
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 {
|
table {
|
||||||
display: inline-block;
|
width: 100%;
|
||||||
margin-top: 3px;
|
height: 100%;
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#statusServerError {
|
table td {
|
||||||
line-height: 20px;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="status intermediate error">
|
<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>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
accesskey="&ffshareContext.accesskey;"
|
accesskey="&ffshareContext.accesskey;"
|
||||||
command="cmd_openSharePage"/>
|
command="cmd_openSharePage"/>
|
||||||
</popup>
|
</popup>
|
||||||
|
|
||||||
</popupset>
|
</popupset>
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,6 +119,7 @@
|
||||||
class="toolbarbutton-1 chromeclass-toolbar-additional"
|
class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||||
label="&ffshareToolbarButton.label;"
|
label="&ffshareToolbarButton.label;"
|
||||||
tooltiptext="&ffshareToolbarButton.tooltip;"
|
tooltiptext="&ffshareToolbarButton.tooltip;"
|
||||||
|
type="checkbox"
|
||||||
command="cmd_openSharePage"/>
|
command="cmd_openSharePage"/>
|
||||||
|
|
||||||
<tabbrowser id="content"/>
|
<tabbrowser id="content"/>
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
<!ENTITY ffshareContext.accesskey "S">
|
<!ENTITY ffshareContext.accesskey "S">
|
||||||
<!ENTITY ffshareMenu.label "Share Page…">
|
<!ENTITY ffshareMenu.label "Share Page…">
|
||||||
<!ENTITY ffshareMenu.accesskey "h">
|
<!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.">
|
<!ENTITY ffshareToolbarButton.tooltip "Use F1 to share the current page via Twitter, Facebook, and more.">
|
||||||
|
|
|
@ -21,52 +21,17 @@
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* */
|
* */
|
||||||
|
|
||||||
.ffshare-frame {
|
#ffshare-toolbar-button > label {
|
||||||
-moz-transition: height 0.2s ease-in;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ffshare-toolbar-button
|
|
||||||
{
|
|
||||||
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
|
|
||||||
}
|
|
||||||
#ffshare-toolbar-button > image {
|
#ffshare-toolbar-button > image {
|
||||||
|
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
#ffshare-popup {
|
#ffshare-toolbar-button[firstRun] > image {
|
||||||
-moz-appearance: none;
|
list-style-image: url("chrome://ffshare/skin/toolbar-button-glow.png");
|
||||||
-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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Styles to style the autocomplete results */
|
/* Styles to style the autocomplete results */
|
||||||
|
@ -74,3 +39,7 @@
|
||||||
.autocomplete-richlistitem[type="ffshare"] .ac-url-box {
|
.autocomplete-richlistitem[type="ffshare"] .ac-url-box {
|
||||||
display: none !important;
|
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):
|
* Contributor(s):
|
||||||
* */
|
* */
|
||||||
|
|
||||||
.ffshare-frame {
|
#ffshare-toolbar-button > label {
|
||||||
-moz-transition: height 0.2s ease-in;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ffshare-toolbar-button
|
|
||||||
{
|
|
||||||
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
|
|
||||||
}
|
|
||||||
#ffshare-toolbar-button > image {
|
#ffshare-toolbar-button > image {
|
||||||
|
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
#ffshare-popup {
|
#ffshare-toolbar-button[firstRun] > image {
|
||||||
-moz-appearance: none;
|
list-style-image: url("chrome://ffshare/skin/toolbar-button-glow.png");
|
||||||
-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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Styles to style the autocomplete results */
|
/* 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 *****
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
* Version: MPL 1.1
|
* Version: MPL 1.1
|
||||||
*
|
*
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
* 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
|
* 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
|
* the License. You may obtain a copy of the License at
|
||||||
* http://www.mozilla.org/MPL/
|
* http://www.mozilla.org/MPL/
|
||||||
*
|
*
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
* for the specific language governing rights and limitations under the
|
* for the specific language governing rights and limitations under the
|
||||||
* License.
|
* License.
|
||||||
*
|
*
|
||||||
* The Original Code is Raindrop.
|
* The Original Code is Raindrop.
|
||||||
*
|
*
|
||||||
* The Initial Developer of the Original Code is
|
* The Initial Developer of the Original Code is
|
||||||
* Mozilla Messaging, Inc..
|
* Mozilla Messaging, Inc..
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||||
* the Initial Developer. All Rights Reserved.
|
* the Initial Developer. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* */
|
* */
|
||||||
|
|
||||||
#ffshare-toolbar-button
|
#ffshare-toolbar-button {
|
||||||
{
|
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
|
||||||
list-style-image: url("chrome://ffshare/skin/toolbar-button.png");
|
-moz-image-region: rect(0px, 35px, 23px, 0px);
|
||||||
-moz-image-region: rect(0px, 35px, 23px, 0px);
|
}
|
||||||
}
|
#ffshare-toolbar-button[disabled="true"],
|
||||||
#ffshare-toolbar-button[disabled="true"],
|
#ffshare-toolbar-button[disabled="true"]:active {
|
||||||
#ffshare-toolbar-button[disabled="true"]:active
|
-moz-image-region: rect(23px, 35px, 46px, 0px);
|
||||||
{
|
}
|
||||||
-moz-image-region: rect(23px, 35px, 46px, 0px);
|
#ffshare-toolbar-button:active {
|
||||||
}
|
-moz-image-region: rect(46px, 35px, 69px, 0px);
|
||||||
#ffshare-toolbar-button:active
|
}
|
||||||
{
|
#ffshare-toolbar-button[checked="true"] {
|
||||||
-moz-image-region: rect(46px, 35px, 69px, 0px);
|
background: none;
|
||||||
}
|
border-color: transparent;
|
||||||
#ffshare-popup {
|
-moz-image-region: rect(46px, 35px, 69px, 0px);
|
||||||
-moz-appearance: none;
|
}
|
||||||
-moz-window-shadow: none;
|
#ffshare-toolbar-button[firstRun] {
|
||||||
background-color: transparent;
|
list-style-image: url("chrome://ffshare/skin/toolbar-button-glow.png");
|
||||||
margin-top: -4px;
|
-moz-image-region: rect(0px, 35px, 23px, 0px);
|
||||||
margin-left: -13px;
|
}
|
||||||
padding-right: 35px; /* not quite 50px but looks very close */
|
|
||||||
min-width: 380px !important;
|
/* Styles to style the autocomplete results */
|
||||||
-moz-border-image: url(chrome://browser/skin/hud-panel.png) 26 18 22 50 / 26px 18px 22px 50px repeat;
|
.autocomplete-richlistitem[type="ffshare"] .ac-site-icon,
|
||||||
color: lightgrey;
|
.autocomplete-richlistitem[type="ffshare"] .ac-url-box {
|
||||||
}
|
display: none !important;
|
||||||
|
}
|
||||||
/* factory reset */
|
|
||||||
#ffshare-popup * {
|
.ffshare-panel {
|
||||||
border: none;
|
width: 441px; /* note this value hard-coded in overlay.js */
|
||||||
outline: none;
|
min-width: 441px !important;
|
||||||
margin: 0;
|
min-height: 234px !important;
|
||||||
padding: 0;
|
}
|
||||||
-moz-padding-start: 0px;
|
|
||||||
-moz-padding-end: 0px;
|
.ffshare-browser {
|
||||||
-moz-margin-start: 0px;
|
width: 400px; /* note this value tied to ffshare-panel width as well */
|
||||||
-moz-margin-end: 0px;
|
height: 100%;
|
||||||
-moz-border-radius: 0px;
|
}
|
||||||
font-family: sans-serif;
|
|
||||||
font-weight: inherit;
|
/* Popup Bounding Box */
|
||||||
font-style: inherit;
|
|
||||||
font-size: 100%;
|
.doorhanger-rtl {
|
||||||
vertical-align: middle;
|
-moz-appearance: none;
|
||||||
-moz-box-sizing: border-box;
|
-moz-window-shadow: none;
|
||||||
list-style-type: none;
|
background-color: transparent;
|
||||||
}
|
margin-top: -10px;
|
||||||
|
margin-left: -16px;
|
||||||
#ffshare-popup description {
|
min-width: 280px;
|
||||||
margin: 5px 0;
|
-moz-border-image: url(chrome://browser/skin/hud-panel.png) 26 10 22 50 / 26px 18px 22px 50px repeat;
|
||||||
font-size: 150%;
|
}
|
||||||
font-weight: bold;
|
|
||||||
}
|
.doorhanger-ltr {
|
||||||
|
-moz-appearance: none;
|
||||||
/* Styles to style the autocomplete results */
|
-moz-window-shadow: none;
|
||||||
.autocomplete-richlistitem[type="ffshare"] .ac-site-icon,
|
background-color: transparent;
|
||||||
.autocomplete-richlistitem[type="ffshare"] .ac-url-box {
|
margin-top: -10px;
|
||||||
display: none !important;
|
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");
|
_("?loaded");
|
||||||
|
|
||||||
__defineGetter__("acDataStorage", function() {
|
__defineGetter__("acDataStorage", function() {
|
||||||
delete this.ffshareAutoCompleteData;
|
|
||||||
Cu.import("resource://ffshare/modules/ffshareAutoCompleteData.js");
|
Cu.import("resource://ffshare/modules/ffshareAutoCompleteData.js");
|
||||||
return ffshareAutoCompleteData;
|
return ffshareAutoCompleteData;
|
||||||
});
|
});
|
||||||
|
@ -64,13 +63,16 @@ FFShareAutoComplete.prototype = {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
findEmails: function findEmails(query) {
|
findEmails: function findEmails(query, field) {
|
||||||
_("findEmails", Array.slice(arguments));
|
_("findEmails", Array.slice(arguments));
|
||||||
|
|
||||||
let result = Cc["@mozilla.org/autocomplete/simple-result;1"].
|
let result = Cc["@mozilla.org/autocomplete/simple-result;1"].
|
||||||
createInstance(Ci.nsIAutoCompleteSimpleResult);
|
createInstance(Ci.nsIAutoCompleteSimpleResult);
|
||||||
result.setSearchString(query);
|
result.setSearchString(query);
|
||||||
|
|
||||||
|
let datadomain = field.getAttribute('autocompletestore');
|
||||||
|
if (!datadomain)
|
||||||
|
return result;
|
||||||
|
|
||||||
//convert the query to only be for things after the comma.
|
//convert the query to only be for things after the comma.
|
||||||
var parts = query.split(','), previousMatch = '';
|
var parts = query.split(','), previousMatch = '';
|
||||||
|
|
||||||
|
@ -83,18 +85,19 @@ FFShareAutoComplete.prototype = {
|
||||||
|
|
||||||
_("query is now: [" + query + "]");
|
_("query is now: [" + query + "]");
|
||||||
_("previousMatch is now: " + previousMatch);
|
_("previousMatch is now: " + previousMatch);
|
||||||
|
_("data domain is: "+datadomain);
|
||||||
let data = acDataStorage.get();
|
let data = acDataStorage.get(datadomain) || {};
|
||||||
|
for (let name in data) {
|
||||||
data.forEach(function (item) {
|
var displayNameLower = name.toLowerCase(),
|
||||||
var displayNameLower = item.displayName.toLowerCase(),
|
emailLower = data[name].email.toLowerCase();
|
||||||
emailLower = item.email.toLowerCase();
|
|
||||||
|
|
||||||
if (displayNameLower.indexOf(query) !== -1 || emailLower.indexOf(query) !== -1) {
|
if (displayNameLower.indexOf(query) !== -1 || emailLower.indexOf(query) !== -1) {
|
||||||
result.appendMatch(previousMatch + item.email + ', ',
|
if (emailLower)
|
||||||
(displayNameLower === emailLower ? item.email : item.displayName + '<' + item.email + '>'), null, 'ffshare');
|
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";
|
let resultCode = result.matchCount ? "RESULT_SUCCESS" : "RESULT_NOMATCH";
|
||||||
_("returning autocomplete " +resultCode+ " result with " + result.matchCount + " items");
|
_("returning autocomplete " +resultCode+ " result with " + result.matchCount + " items");
|
||||||
|
@ -106,7 +109,7 @@ _("previousMatch is now: " + previousMatch);
|
||||||
_("FFShareAutoComplete search", Array.slice(arguments));
|
_("FFShareAutoComplete search", Array.slice(arguments));
|
||||||
|
|
||||||
if (this.isShareType(name, field))
|
if (this.isShareType(name, field))
|
||||||
return this.findEmails(query);
|
return this.findEmails(query, field);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<em:id>ffshare@mozilla.org</em:id>
|
<em:id>ffshare@mozilla.org</em:id>
|
||||||
<em:type>2</em:type>
|
<em:type>2</em:type>
|
||||||
<em:name>F1 by Mozilla Labs</em:name>
|
<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:creator>Mozilla</em:creator>
|
||||||
<em:contributor></em:contributor>
|
<em:contributor></em:contributor>
|
||||||
<em:homepageURL>http://f1.mozillamessaging.com/</em:homepageURL>
|
<em:homepageURL>http://f1.mozillamessaging.com/</em:homepageURL>
|
||||||
|
@ -13,8 +13,8 @@
|
||||||
<em:targetApplication>
|
<em:targetApplication>
|
||||||
<Description>
|
<Description>
|
||||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- Firefox -->
|
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- Firefox -->
|
||||||
<em:minVersion>3.6</em:minVersion>
|
<em:minVersion>3.6.6</em:minVersion>
|
||||||
<em:maxVersion>4.0b9pre</em:maxVersion>
|
<em:maxVersion>4.0b12pre</em:maxVersion>
|
||||||
</Description>
|
</Description>
|
||||||
</em:targetApplication>
|
</em:targetApplication>
|
||||||
</Description>
|
</Description>
|
||||||
|
|
|
@ -20,16 +20,26 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* */
|
* */
|
||||||
|
const Cu = Components.utils;
|
||||||
|
|
||||||
let EXPORTED_SYMBOLS = ["ffshareAutoCompleteData"];
|
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 = {
|
let ffshareAutoCompleteData = {
|
||||||
get: function () {
|
get: function (domain) {
|
||||||
return data;
|
_("XXX getting data for "+domain);
|
||||||
|
return data[domain];
|
||||||
},
|
},
|
||||||
set: function (newData) {
|
set: function (acdata) {
|
||||||
data = (newData || []);
|
_("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>
|
* Shane Caraveo <shane@caraveo.com>
|
||||||
* Myk Melez <myk@mozilla.org>
|
* Myk Melez <myk@mozilla.org>
|
||||||
* Justin Dolske <dolske@mozilla.com>
|
* Justin Dolske <dolske@mozilla.com>
|
||||||
|
* Erik Vold <erikvvold@gmail.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* 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
|
* 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. */
|
/* Inject the People content API into window.navigator objects. */
|
||||||
/* Partly based on code in the Geode extension. */
|
/* Partly based on code in the Geode extension. */
|
||||||
|
|
||||||
const Cc = Components.classes;
|
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||||
const Ci = Components.interfaces;
|
|
||||||
const Cu = Components.utils;
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
let EXPORTED_SYMBOLS = ["InjectorInit"];
|
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) {
|
function InjectorInit(window) {
|
||||||
if (window.injector) return;
|
if (window.injector) return;
|
||||||
window.injector = {
|
window.injector = {
|
||||||
providers: [],
|
providers: [],
|
||||||
onLoad: function() {
|
onLoad: function() {
|
||||||
var obs = Components.classes["@mozilla.org/observer-service;1"].
|
var obs = Cc["@mozilla.org/observer-service;1"].
|
||||||
getService(Components.interfaces.nsIObserverService);
|
getService(Ci.nsIObserverService);
|
||||||
obs.addObserver(this, 'content-document-global-created', false);
|
obs.addObserver(this, 'content-document-global-created', false);
|
||||||
},
|
},
|
||||||
|
|
||||||
onUnload: function() {
|
onUnload: function() {
|
||||||
var obs = Components.classes["@mozilla.org/observer-service;1"].
|
var obs = Cc["@mozilla.org/observer-service;1"].
|
||||||
getService(Components.interfaces.nsIObserverService);
|
getService(Ci.nsIObserverService);
|
||||||
obs.removeObserver(this, 'content-document-global-created');
|
obs.removeObserver(this, 'content-document-global-created');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -152,12 +151,12 @@ function InjectorInit(window) {
|
||||||
observe: function(aSubject, aTopic, aData) {
|
observe: function(aSubject, aTopic, aData) {
|
||||||
if (!aSubject.location.href) return;
|
if (!aSubject.location.href) return;
|
||||||
// is this window a child of OUR XUL window?
|
// is this window a child of OUR XUL window?
|
||||||
var mainWindow = aSubject.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
var mainWindow = aSubject.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
|
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||||
.rootTreeItem
|
.rootTreeItem
|
||||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
.getInterface(Components.interfaces.nsIDOMWindow);
|
.getInterface(Ci.nsIDOMWindow);
|
||||||
if (mainWindow != window) {
|
if (mainWindow != window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,9 @@ Subject line for emails, not supported by all services.
|
||||||
"""),
|
"""),
|
||||||
api_arg('picture', 'string', False, None, None, """
|
api_arg('picture', 'string', False, None, None, """
|
||||||
URL to publicly available thumbnail, not supported by all services.
|
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, """
|
api_arg('description', 'string', False, None, None, """
|
||||||
Site provided description of the shared item, not supported by all services.
|
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.openidconsumer import OpenIDResponder
|
||||||
from linkdrop.lib.oauth import twitter_
|
from linkdrop.lib.oauth import twitter_
|
||||||
from linkdrop.lib.oauth import yahoo_
|
from linkdrop.lib.oauth import yahoo_
|
||||||
|
from linkdrop.lib.oauth import linkedin_
|
||||||
|
|
||||||
__all__ = ['get_provider']
|
__all__ = ['get_provider']
|
||||||
|
|
||||||
|
@ -36,7 +37,8 @@ _providers = {
|
||||||
facebook_.domain: facebook_,
|
facebook_.domain: facebook_,
|
||||||
google_.domain: google_,
|
google_.domain: google_,
|
||||||
"googleapps.com": google_,
|
"googleapps.com": google_,
|
||||||
yahoo_.domain: yahoo_
|
yahoo_.domain: yahoo_,
|
||||||
|
linkedin_.domain: linkedin_
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_provider(provider):
|
def get_provider(provider):
|
||||||
|
|
|
@ -33,13 +33,14 @@ import httplib2
|
||||||
import urllib
|
import urllib
|
||||||
import random
|
import random
|
||||||
import copy
|
import copy
|
||||||
|
import logging
|
||||||
|
|
||||||
from pylons import config, request, response, session, tmpl_context as c, url
|
from pylons import config, request, response, session, tmpl_context as c, url
|
||||||
from pylons.controllers.util import abort, redirect
|
from pylons.controllers.util import abort, redirect
|
||||||
from linkdrop.lib.oauth.base import OAuth2
|
from linkdrop.lib.oauth.base import OAuth2
|
||||||
|
|
||||||
domain = 'facebook.com'
|
domain = 'facebook.com'
|
||||||
|
log = logging.getLogger(domain)
|
||||||
|
|
||||||
# this function is a derivative of:
|
# this function is a derivative of:
|
||||||
# http://code.activestate.com/recipes/146306-http-client-to-post-using-multipartform-data/
|
# http://code.activestate.com/recipes/146306-http-client-to-post-using-multipartform-data/
|
||||||
|
@ -210,36 +211,76 @@ class api():
|
||||||
'status': status})
|
'status': status})
|
||||||
return error
|
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))
|
url = url +"?"+urllib.urlencode(dict(access_token=self.access_token))
|
||||||
|
headers = None
|
||||||
content_type, body = encode_multipart_formdata(body)
|
if body:
|
||||||
headers = {
|
content_type, body = encode_multipart_formdata(body)
|
||||||
'Content-type': content_type,
|
headers = {
|
||||||
'Content-Length': str(len(body))
|
'Content-type': content_type,
|
||||||
}
|
'Content-Length': str(len(body))
|
||||||
resp, content = httplib2.Http().request(url, 'POST', headers=headers, body=body)
|
}
|
||||||
|
resp, content = httplib2.Http().request(url, method=method, headers=headers, body=body)
|
||||||
|
|
||||||
data = json.loads(content)
|
data = json.loads(content)
|
||||||
result = error = None
|
result = error = None
|
||||||
if 'id' in data:
|
if 'id' in data:
|
||||||
result = data
|
result = data
|
||||||
result[domain] = data['id']
|
result[domain] = data['id']
|
||||||
|
elif 'data' in data:
|
||||||
|
result = data
|
||||||
|
result[domain] = None
|
||||||
else:
|
else:
|
||||||
error = self._make_error(data, resp)
|
error = self._make_error(data, resp)
|
||||||
|
|
||||||
return result, error
|
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={}):
|
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 = {
|
body = {
|
||||||
"message": message
|
"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']:
|
return self.rawcall(url, body, "POST")
|
||||||
if arg in options:
|
|
||||||
body[arg] = options[arg]
|
|
||||||
|
|
||||||
return self.rawcall(url, body)
|
|
||||||
|
|
||||||
|
|
||||||
|
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.multipart import MIMEMultipart
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
|
from email.mime.image import MIMEImage
|
||||||
from email.header import Header
|
from email.header import Header
|
||||||
|
|
||||||
from pylons import config, request, response, session, tmpl_context as c, url
|
from pylons import config, request, response, session, tmpl_context as c, url
|
||||||
|
@ -193,7 +194,6 @@ class responder(OpenIDResponder):
|
||||||
|
|
||||||
profile = result_data['profile']
|
profile = result_data['profile']
|
||||||
provider = domain
|
provider = domain
|
||||||
import sys; print >> sys.stderr, "credential provider is ", profile.get('providerName')
|
|
||||||
if profile.get('providerName').lower() == 'openid':
|
if profile.get('providerName').lower() == 'openid':
|
||||||
provider = 'googleapps.com'
|
provider = 'googleapps.com'
|
||||||
userid = profile.get('verifiedEmail','')
|
userid = profile.get('verifiedEmail','')
|
||||||
|
@ -285,8 +285,25 @@ class api():
|
||||||
c.description = description
|
c.description = description
|
||||||
c.message = message
|
c.message = message
|
||||||
|
|
||||||
part2 = MIMEText(render('/html_email.mako').encode('utf-8'), 'html')
|
c.thumbnail = (options.get('picture_base64', "") != "")
|
||||||
part2.set_charset('utf-8')
|
|
||||||
|
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
|
# get the title, or the long url or the short url or nothing
|
||||||
# wrap these in literal for text email
|
# wrap these in literal for text email
|
||||||
|
@ -333,7 +350,7 @@ class api():
|
||||||
return result, error
|
return result, error
|
||||||
|
|
||||||
def getgroup_id(self, group):
|
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'
|
method = 'GET'
|
||||||
client = oauth.Client(self.consumer, self.oauth_token)
|
client = oauth.Client(self.consumer, self.oauth_token)
|
||||||
resp, content = client.request(url, method)
|
resp, content = client.request(url, method)
|
||||||
|
@ -347,7 +364,13 @@ class api():
|
||||||
|
|
||||||
def getcontacts(self, start=0, page=25, group=None):
|
def getcontacts(self, start=0, page=25, group=None):
|
||||||
contacts = []
|
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'
|
method = 'GET'
|
||||||
if start > 0:
|
if start > 0:
|
||||||
url = url + "&start-index=%d" % (start,)
|
url = url + "&start-index=%d" % (start,)
|
||||||
|
@ -363,6 +386,7 @@ class api():
|
||||||
# itemsPerPage, startIndex, totalResults
|
# itemsPerPage, startIndex, totalResults
|
||||||
client = oauth.Client(self.consumer, self.oauth_token)
|
client = oauth.Client(self.consumer, self.oauth_token)
|
||||||
resp, content = client.request(url, method)
|
resp, content = client.request(url, method)
|
||||||
|
|
||||||
if int(resp.status) != 200:
|
if int(resp.status) != 200:
|
||||||
error={"provider": domain,
|
error={"provider": domain,
|
||||||
"message": content,
|
"message": content,
|
||||||
|
@ -371,7 +395,6 @@ class api():
|
||||||
return None, error
|
return None, error
|
||||||
|
|
||||||
feed = gdata.contacts.ContactsFeedFromString(content)
|
feed = gdata.contacts.ContactsFeedFromString(content)
|
||||||
from pprint import pprint
|
|
||||||
for entry in feed.entry:
|
for entry in feed.entry:
|
||||||
#print entry.group_membership_info
|
#print entry.group_membership_info
|
||||||
p = {
|
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'] }]
|
poco['photos'] = [ { 'type': u'profile', "value" : user['profile_image_url'] }]
|
||||||
if user.get('created_at', None):
|
if user.get('created_at', None):
|
||||||
poco['published'] = user['created_at']
|
poco['published'] = user['created_at']
|
||||||
|
|
||||||
|
account = {'domain': 'twitter.com',
|
||||||
|
'userid': user['id'],
|
||||||
|
'username': user['screen_name'] }
|
||||||
|
poco['accounts'] = [account]
|
||||||
|
|
||||||
return poco
|
return poco
|
||||||
|
|
||||||
class responder(OAuth1):
|
class responder(OAuth1):
|
||||||
|
@ -157,7 +163,11 @@ class api():
|
||||||
# some reason we dont have a short url, add the long url
|
# some reason we dont have a short url, add the long url
|
||||||
message += " %s" % longurl
|
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']
|
result[domain] = result['id']
|
||||||
except TwitterHTTPError, exc:
|
except TwitterHTTPError, exc:
|
||||||
try:
|
try:
|
||||||
|
@ -195,4 +205,35 @@ class api():
|
||||||
'status': exc.e.code
|
'status': exc.e.code
|
||||||
}
|
}
|
||||||
return result, error
|
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 json
|
||||||
import copy
|
import copy
|
||||||
from rfc822 import AddressList
|
from rfc822 import AddressList
|
||||||
|
import logging
|
||||||
|
|
||||||
from pylons import config, request, response, session, tmpl_context as c, url
|
from pylons import config, request, response, session, tmpl_context as c, url
|
||||||
from pylons.controllers.util import abort, redirect
|
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'
|
YAHOO_OAUTH = 'https://api.login.yahoo.com/oauth/v2/get_token'
|
||||||
|
|
||||||
domain = 'yahoo.com'
|
domain = 'yahoo.com'
|
||||||
|
log = logging.getLogger(domain)
|
||||||
|
|
||||||
class responder(OpenIDResponder):
|
class responder(OpenIDResponder):
|
||||||
def __init__(self, consumer=None, oauth_key=None, oauth_secret=None, request_attributes=None, *args,
|
def __init__(self, consumer=None, oauth_key=None, oauth_secret=None, request_attributes=None, *args,
|
||||||
|
@ -100,12 +102,14 @@ class responder(OpenIDResponder):
|
||||||
'userid': userid,
|
'userid': userid,
|
||||||
'username': username }
|
'username': username }
|
||||||
profile['accounts'] = [account]
|
profile['accounts'] = [account]
|
||||||
|
profile['xoauth_yahoo_guid'] = result_data['xoauth_yahoo_guid']
|
||||||
return result_data
|
return result_data
|
||||||
|
|
||||||
|
|
||||||
class api():
|
class api():
|
||||||
endpoints = {
|
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):
|
def __init__(self, account):
|
||||||
|
@ -117,7 +121,7 @@ class api():
|
||||||
self.consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
|
self.consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
|
||||||
self.sigmethod = oauth.SignatureMethod_HMAC_SHA1()
|
self.sigmethod = oauth.SignatureMethod_HMAC_SHA1()
|
||||||
|
|
||||||
def rawcall(self, url, method, args, options={}):
|
def jsonrpc(self, url, method, args, options={}):
|
||||||
headers = {
|
headers = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
|
@ -161,6 +165,31 @@ class api():
|
||||||
|
|
||||||
return result, error
|
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={}):
|
def sendmessage(self, message, options={}):
|
||||||
result = error = None
|
result = error = None
|
||||||
|
|
||||||
|
@ -194,6 +223,7 @@ class api():
|
||||||
c.title = title
|
c.title = title
|
||||||
c.description = description
|
c.description = description
|
||||||
c.message = message
|
c.message = message
|
||||||
|
c.thumbnail = False
|
||||||
|
|
||||||
html_message = render('/html_email.mako').encode('utf-8')
|
html_message = render('/html_email.mako').encode('utf-8')
|
||||||
|
|
||||||
|
@ -222,6 +252,42 @@ class api():
|
||||||
"savecopy":1
|
"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>
|
<a target="_blank" style="color:#00A0FF;font-size:16px;" href="${c.longurl}">${c.title}</a>
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</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:
|
% 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))}
|
${context.write(c.safeHTML(c.description))}
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% 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>
|
||||||
<div class="footer" style="font-size:12px;color:#444;">
|
<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>
|
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(
|
setup(
|
||||||
name='linkdrop',
|
name='linkdrop',
|
||||||
version='0.1.6.1',
|
version='0.1.8',
|
||||||
description='',
|
description='',
|
||||||
author='',
|
author='',
|
||||||
author_email='',
|
author_email='',
|
||||||
|
@ -45,9 +45,9 @@ setup(
|
||||||
"python-dateutil",
|
"python-dateutil",
|
||||||
"python-openid",
|
"python-openid",
|
||||||
"python-memcached",
|
"python-memcached",
|
||||||
"twitter",
|
|
||||||
"gdata", # google api support
|
"gdata", # google api support
|
||||||
"sqlalchemy-migrate>=0.5.4",
|
"sqlalchemy-migrate>=0.5.4",
|
||||||
|
"twitter>=1.4.2"
|
||||||
],
|
],
|
||||||
setup_requires=["PasteScript>=1.6.3"],
|
setup_requires=["PasteScript>=1.6.3"],
|
||||||
packages=find_packages(exclude=['ez_setup']),
|
packages=find_packages(exclude=['ez_setup']),
|
||||||
|
@ -63,6 +63,7 @@ setup(
|
||||||
entry_points="""
|
entry_points="""
|
||||||
[paste.app_factory]
|
[paste.app_factory]
|
||||||
main = linkdrop.config.middleware:make_app
|
main = linkdrop.config.middleware:make_app
|
||||||
|
static = linkdrop.static:make_static
|
||||||
|
|
||||||
[paste.filter_app_factory]
|
[paste.filter_app_factory]
|
||||||
csrf = linkdrop.csrf:make_csrf_filter_app
|
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.
|
* @license 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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/sh
|
#!/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 "$@"
|
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
|
#!/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 "$@"
|
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
|
* THIS BUILD FILE WILL NOT WORK. It is referencing paths that probably
|
||||||
* do not exist on your machine. Just use it as a guide.
|
* 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
|
//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.
|
//then it assumed your scripts are in a subdirectory under this path.
|
||||||
//This option is not required. If it is not specified, then baseUrl
|
//This option is not required. If it is not specified, then baseUrl
|
||||||
|
@ -75,8 +75,8 @@
|
||||||
useStrict: false,
|
useStrict: false,
|
||||||
|
|
||||||
//Specify build pragmas. If the source files contain comments like so:
|
//Specify build pragmas. If the source files contain comments like so:
|
||||||
//>>excludeStart("requireExcludeModify", pragmas.requireExcludeModify);
|
//>>excludeStart("fooExclude", pragmas.fooExclude);
|
||||||
//>>excludeEnd("requireExcludeModify");
|
//>>excludeEnd("fooExclude");
|
||||||
//Then the comments that start with //>> are the build pragmas.
|
//Then the comments that start with //>> are the build pragmas.
|
||||||
//excludeStart/excludeEnd and includeStart/includeEnd work, and the
|
//excludeStart/excludeEnd and includeStart/includeEnd work, and the
|
||||||
//the pragmas value to the includeStart or excludeStart lines
|
//the pragmas value to the includeStart or excludeStart lines
|
||||||
|
@ -84,27 +84,12 @@
|
||||||
//lines should be included or excluded.
|
//lines should be included or excluded.
|
||||||
pragmas: {
|
pragmas: {
|
||||||
//Indicates require will be included with jquery.
|
//Indicates require will be included with jquery.
|
||||||
jquery: true,
|
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
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//Skip processing for pragmas.
|
//Skip processing for pragmas.
|
||||||
skipPragmas: false,
|
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
|
//If skipModuleInsertion is false, then files that do not use require.def
|
||||||
//to define modules will get a require.def() placeholder inserted for them.
|
//to define modules will get a require.def() placeholder inserted for them.
|
||||||
//Also, require.pause/resume calls will be inserted.
|
//Also, require.pause/resume calls will be inserted.
|
||||||
|
@ -125,7 +110,7 @@
|
||||||
//built file unless the locale: section is set above.
|
//built file unless the locale: section is set above.
|
||||||
{
|
{
|
||||||
name: "foo/bar/bop",
|
name: "foo/bar/bop",
|
||||||
|
|
||||||
//Should the contents of require.js be included in the optimized module.
|
//Should the contents of require.js be included in the optimized module.
|
||||||
//Defaults to false.
|
//Defaults to false.
|
||||||
includeRequire: true,
|
includeRequire: true,
|
||||||
|
@ -137,7 +122,7 @@
|
||||||
//contain any of the other build options in this file.
|
//contain any of the other build options in this file.
|
||||||
override: {
|
override: {
|
||||||
pragmas: {
|
pragmas: {
|
||||||
requireExcludeModify: true
|
fooExclude: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -174,5 +159,4 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
/**
|
/**
|
||||||
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
* @license 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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*jslint regexp: false, plusplus: false, nomen: false */
|
/*jslint regexp: false, plusplus: false, nomen: false */
|
||||||
/*global java: false, lang: false, fileUtil: false, optimize: false,
|
/*global java: false, lang: false, fileUtil: false, optimize: false,
|
||||||
load: false, quit: false, print: false, logger: false, require: false,
|
load: false, quit: false, print: false, logger: false, require: false,
|
||||||
pragma: false */
|
pragma: false, parse: false */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
@ -21,16 +21,16 @@ var build, buildBaseConfig;
|
||||||
optimize: "closure",
|
optimize: "closure",
|
||||||
optimizeCss: "standard.keepLines",
|
optimizeCss: "standard.keepLines",
|
||||||
inlineText: true,
|
inlineText: true,
|
||||||
execModules: false
|
isBuild: true
|
||||||
};
|
};
|
||||||
|
|
||||||
build = function (args) {
|
build = function (args) {
|
||||||
var requireBuildPath, buildFile, baseUrlFile, buildPaths, deps, fileName, fileNames,
|
var requireBuildPath, buildFile, baseUrlFile, buildPaths, deps, fileName, fileNames,
|
||||||
prop, props, paths, path, i, fileContents, buildFileContents = "",
|
prop, props, paths, path, i, fileContents, buildFileContents = "",
|
||||||
doClosure, requireContents, pluginContents, pluginBuildFileContents,
|
doClosure, requireContents, pluginBuildFileContents,
|
||||||
baseConfig, override, builtRequirePath, cmdConfig, config,
|
baseConfig, override, builtRequirePath, cmdConfig, config,
|
||||||
modules, module, moduleName, builtModule;
|
modules, module, moduleName, builtModule, srcPath, buildContext;
|
||||||
|
|
||||||
if (!args || args.length < 2) {
|
if (!args || args.length < 2) {
|
||||||
print("java -jar path/to/js.jar build.js directory/containing/build.js/ build.js\n" +
|
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.");
|
"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) !== "/") {
|
if (requireBuildPath.charAt(requireBuildPath.length - 1) !== "/") {
|
||||||
requireBuildPath += "/";
|
requireBuildPath += "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
["lang", "logger", "fileUtil", "parse", "optimize", "pragma", "build"].forEach(function (path) {
|
["lang", "logger", "fileUtil", "parse", "optimize", "pragma", "build"].forEach(function (path) {
|
||||||
load(requireBuildPath + "jslib/" + path + ".js");
|
load(requireBuildPath + "jslib/" + path + ".js");
|
||||||
});
|
});
|
||||||
|
|
||||||
//Next args can include a build file path as well as other build args.
|
//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
|
//build file path comes first. If it does not contain an = then it is
|
||||||
//a build file path. Otherwise, just all build args.
|
//a build file path. Otherwise, just all build args.
|
||||||
|
@ -57,42 +57,47 @@ var build, buildBaseConfig;
|
||||||
} else {
|
} else {
|
||||||
args.splice(0, 1);
|
args.splice(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remaining args are options to the build
|
//Remaining args are options to the build
|
||||||
cmdConfig = build.convertArrayToObject(args);
|
cmdConfig = build.convertArrayToObject(args);
|
||||||
cmdConfig.buildFile = buildFile;
|
cmdConfig.buildFile = buildFile;
|
||||||
cmdConfig.requireBuildPath = requireBuildPath;
|
cmdConfig.requireBuildPath = requireBuildPath;
|
||||||
|
|
||||||
config = build.createConfig(cmdConfig);
|
config = build.createConfig(cmdConfig);
|
||||||
paths = config.paths;
|
paths = config.paths;
|
||||||
|
|
||||||
//Load require.js with the build patches.
|
//Load require.js with the build patches.
|
||||||
load(config.requireUrl);
|
load(config.requireUrl);
|
||||||
load(requireBuildPath + "jslib/requirePatch.js");
|
load(requireBuildPath + "jslib/requirePatch.js");
|
||||||
|
|
||||||
if (!config.out && !config.cssIn) {
|
if (!config.out && !config.cssIn) {
|
||||||
//This is not just a one-off file build but a full build profile, with
|
//This is not just a one-off file build but a full build profile, with
|
||||||
//lots of files to process.
|
//lots of files to process.
|
||||||
|
|
||||||
//First copy all the baseUrl content
|
//First copy all the baseUrl content
|
||||||
fileUtil.copyDir((config.appDir || config.baseUrl), config.dir, /\w/, true);
|
fileUtil.copyDir((config.appDir || config.baseUrl), config.dir, /\w/, true);
|
||||||
|
|
||||||
//Adjust baseUrl if config.appDir is in play, and set up build output paths.
|
//Adjust baseUrl if config.appDir is in play, and set up build output paths.
|
||||||
buildPaths = {};
|
buildPaths = {};
|
||||||
if (config.appDir) {
|
if (config.appDir) {
|
||||||
config.dirBaseUrl = config.dir + config.baseUrl;
|
|
||||||
config.baseUrl = config.appDir + config.baseUrl;
|
|
||||||
//All the paths should be inside the appDir
|
//All the paths should be inside the appDir
|
||||||
buildPaths = paths;
|
buildPaths = paths;
|
||||||
} else {
|
} else {
|
||||||
config.dirBaseUrl = config.dir;
|
|
||||||
//If no appDir, then make sure to copy the other paths to this directory.
|
//If no appDir, then make sure to copy the other paths to this directory.
|
||||||
for (prop in paths) {
|
for (prop in paths) {
|
||||||
if (paths.hasOwnProperty(prop)) {
|
if (paths.hasOwnProperty(prop)) {
|
||||||
//Set up build path for each path prefix.
|
//Set up build path for each path prefix.
|
||||||
buildPaths[prop] = prop.replace(/\./g, "/");
|
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)
|
//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,
|
baseUrl: config.baseUrl,
|
||||||
paths: paths
|
paths: paths
|
||||||
});
|
});
|
||||||
|
buildContext = require.s.contexts._;
|
||||||
modules = config.modules;
|
modules = config.modules;
|
||||||
|
|
||||||
if (modules) {
|
if (modules) {
|
||||||
modules.forEach(function (module) {
|
modules.forEach(function (module) {
|
||||||
if (module.name) {
|
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,
|
//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.
|
//as indicated by a true "create" property on the module, then throw an error.
|
||||||
if (!(new java.io.File(module._sourcePath)).exists() && !module.create) {
|
if (!(new java.io.File(module._sourcePath)).exists() && !module.create) {
|
||||||
|
@ -138,11 +144,11 @@ var build, buildBaseConfig;
|
||||||
};
|
};
|
||||||
lang.mixin(baseConfig, config);
|
lang.mixin(baseConfig, config);
|
||||||
require(baseConfig);
|
require(baseConfig);
|
||||||
|
|
||||||
if (modules) {
|
if (modules) {
|
||||||
modules.forEach(function (module) {
|
modules.forEach(function (module) {
|
||||||
if (module.name) {
|
if (module.name) {
|
||||||
module._buildPath = require.nameToUrl(module.name, null, require.s.ctxName);
|
module._buildPath = buildContext.nameToUrl(module.name, null);
|
||||||
if (!module.create) {
|
if (!module.create) {
|
||||||
fileUtil.copyFile(module._sourcePath, module._buildPath);
|
fileUtil.copyFile(module._sourcePath, module._buildPath);
|
||||||
}
|
}
|
||||||
|
@ -214,16 +220,16 @@ var build, buildBaseConfig;
|
||||||
//Normal optimizations across modules.
|
//Normal optimizations across modules.
|
||||||
|
|
||||||
//JS optimizations.
|
//JS optimizations.
|
||||||
fileNames = fileUtil.getFilteredFileList(config.dir, /\.js$/, true);
|
fileNames = fileUtil.getFilteredFileList(config.dir, /\.js$/, true);
|
||||||
for (i = 0; (fileName = fileNames[i]); i++) {
|
for (i = 0; (fileName = fileNames[i]); i++) {
|
||||||
optimize.jsFile(fileName, fileName, config);
|
optimize.jsFile(fileName, fileName, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
//CSS optimizations
|
//CSS optimizations
|
||||||
if (config.optimizeCss && config.optimizeCss !== "none") {
|
if (config.optimizeCss && config.optimizeCss !== "none") {
|
||||||
optimize.css(config.dir, config);
|
optimize.css(config.dir, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
//All module layers are done, write out the build.txt file.
|
//All module layers are done, write out the build.txt file.
|
||||||
fileUtil.saveUtf8File(config.dir + "build.txt", buildFileContents);
|
fileUtil.saveUtf8File(config.dir + "build.txt", buildFileContents);
|
||||||
}
|
}
|
||||||
|
@ -237,7 +243,7 @@ var build, buildBaseConfig;
|
||||||
if (buildFileContents) {
|
if (buildFileContents) {
|
||||||
print(buildFileContents);
|
print(buildFileContents);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -281,6 +287,17 @@ var build, buildBaseConfig;
|
||||||
return result; //Object
|
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.
|
* Creates a config object for an optimization build.
|
||||||
* It will also read the build profile if it is available, to create
|
* It will also read the build profile if it is available, to create
|
||||||
|
@ -295,7 +312,7 @@ var build, buildBaseConfig;
|
||||||
build.createConfig = function (cfg) {
|
build.createConfig = function (cfg) {
|
||||||
/*jslint evil: true */
|
/*jslint evil: true */
|
||||||
var config = {}, baseUrl, buildFileContents, buildFileConfig,
|
var config = {}, baseUrl, buildFileContents, buildFileConfig,
|
||||||
paths, props, i, prop;
|
paths, props, i, prop, buildFile, absFilePath, originalBaseUrl;
|
||||||
|
|
||||||
lang.mixin(config, buildBaseConfig);
|
lang.mixin(config, buildBaseConfig);
|
||||||
lang.mixin(config, cfg, true);
|
lang.mixin(config, cfg, true);
|
||||||
|
@ -313,20 +330,19 @@ var build, buildBaseConfig;
|
||||||
|
|
||||||
if (config.buildFile) {
|
if (config.buildFile) {
|
||||||
//A build file exists, load it to get more config.
|
//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
|
//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
|
//that has a build profile, and not just command line args with an in=path
|
||||||
if (!config.buildFile.exists()) {
|
if (!buildFile.exists()) {
|
||||||
throw new Error("ERROR: build file does not exist: " + config.buildFile.getAbsolutePath());
|
throw new Error("ERROR: build file does not exist: " + buildFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
config.baseUrl = fileUtil.absPath(config.buildFile.getParentFile());
|
absFilePath = config.baseUrl = fileUtil.absPath(buildFile.getParentFile()).replace(lang.backSlashRegExp, '/');
|
||||||
config.buildFile = fileUtil.absPath(config.buildFile);
|
|
||||||
config.dir = config.baseUrl + "/build/";
|
config.dir = config.baseUrl + "/build/";
|
||||||
|
|
||||||
//Load build file options.
|
//Load build file options.
|
||||||
buildFileContents = fileUtil.readFile(config.buildFile);
|
buildFileContents = fileUtil.readFile(buildFile);
|
||||||
buildFileConfig = eval("(" + buildFileContents + ")");
|
buildFileConfig = eval("(" + buildFileContents + ")");
|
||||||
lang.mixin(config, buildFileConfig, true);
|
lang.mixin(config, buildFileConfig, true);
|
||||||
|
|
||||||
|
@ -334,7 +350,6 @@ var build, buildBaseConfig;
|
||||||
//args should take precedence over build file values.
|
//args should take precedence over build file values.
|
||||||
lang.mixin(config, cfg, true);
|
lang.mixin(config, cfg, true);
|
||||||
} else {
|
} else {
|
||||||
//Base URL is relative to the in file.
|
|
||||||
if (!config.out && !config.cssIn) {
|
if (!config.out && !config.cssIn) {
|
||||||
throw new Error("ERROR: 'out' or 'cssIn' option missing.");
|
throw new Error("ERROR: 'out' or 'cssIn' option missing.");
|
||||||
}
|
}
|
||||||
|
@ -347,6 +362,9 @@ var build, buildBaseConfig;
|
||||||
if (!config.cssIn && !cfg.baseUrl) {
|
if (!config.cssIn && !cfg.baseUrl) {
|
||||||
throw new Error("ERROR: 'baseUrl' option missing.");
|
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) {
|
if (config.out && !config.cssIn) {
|
||||||
|
@ -377,7 +395,8 @@ var build, buildBaseConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Adjust the path properties as appropriate.
|
//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"];
|
props = ["appDir", "dir", "baseUrl"];
|
||||||
for (i = 0; (prop = props[i]); i++) {
|
for (i = 0; (prop = props[i]); i++) {
|
||||||
if (config[prop]) {
|
if (config[prop]) {
|
||||||
|
@ -385,6 +404,34 @@ var build, buildBaseConfig;
|
||||||
if (config[prop].charAt(config[prop].length - 1) !== "/") {
|
if (config[prop].charAt(config[prop].length - 1) !== "/") {
|
||||||
config[prop] += "/";
|
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
|
* Uses the module build config object to trace the dependencies for the
|
||||||
* given module.
|
* given module.
|
||||||
*
|
*
|
||||||
* @param {Object} module the module object from the build config info.
|
* @param {Object} module the module object from the build config info.
|
||||||
* @param {Object} the build config object.
|
* @param {Object} the build config object.
|
||||||
*
|
*
|
||||||
|
@ -445,7 +492,7 @@ var build, buildBaseConfig;
|
||||||
*/
|
*/
|
||||||
build.traceDependencies = function (module, config) {
|
build.traceDependencies = function (module, config) {
|
||||||
var include, override, url, layer, prop,
|
var include, override, url, layer, prop,
|
||||||
context = require.s.contexts[require.s.ctxName],
|
context = require.s.contexts._,
|
||||||
baseConfig = context.config;
|
baseConfig = context.config;
|
||||||
|
|
||||||
//Reset some state set up in requirePatch.js, and clean up require's
|
//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
|
//but grab the latest value from inside require() since it was reset
|
||||||
//since our last context reference.
|
//since our last context reference.
|
||||||
layer = require._layer;
|
layer = require._layer;
|
||||||
layer.specified = require.s.contexts[require.s.ctxName].specified;
|
layer.specified = context.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Reset config
|
//Reset config
|
||||||
if (module.override) {
|
if (module.override) {
|
||||||
require(baseConfig);
|
require(baseConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
return layer;
|
return layer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uses the module build config object to create an flattened version
|
* Uses the module build config object to create an flattened version
|
||||||
* of the module, with deep dependencies included.
|
* of the module, with deep dependencies included.
|
||||||
*
|
*
|
||||||
* @param {Object} module the module object from the build config info.
|
* @param {Object} module the module object from the build config info.
|
||||||
*
|
*
|
||||||
* @param {Object} layer the layer object returned from build.traceDependencies.
|
* @param {Object} layer the layer object returned from build.traceDependencies.
|
||||||
*
|
*
|
||||||
* @param {Object} the build config object.
|
* @param {Object} the build config object.
|
||||||
*
|
*
|
||||||
* @returns {Object} with two properties: "text", the text of the flattened
|
* @returns {Object} with two properties: "text", the text of the flattened
|
||||||
|
@ -522,10 +548,15 @@ var build, buildBaseConfig;
|
||||||
*/
|
*/
|
||||||
build.flattenModule = function (module, layer, config) {
|
build.flattenModule = function (module, layer, config) {
|
||||||
var buildFileContents = "", requireContents = "",
|
var buildFileContents = "", requireContents = "",
|
||||||
pluginContents = "", pluginBuildFileContents = "", includeRequire,
|
context = require.s.contexts._,
|
||||||
anonDefRegExp = /require\s*\.\s*def\s*\(\s*(\[|f|\{)/,
|
//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,
|
prop, path, reqIndex, fileContents, currContents,
|
||||||
i, moduleName, specified, deps;
|
i, moduleName, specified, deps, includeRequire,
|
||||||
|
parts, builder;
|
||||||
|
|
||||||
//Use override settings, particularly for pragmas
|
//Use override settings, particularly for pragmas
|
||||||
if (module.override) {
|
if (module.override) {
|
||||||
|
@ -540,8 +571,6 @@ var build, buildBaseConfig;
|
||||||
|
|
||||||
//If the file wants require.js added to the module, add it now
|
//If the file wants require.js added to the module, add it now
|
||||||
requireContents = "";
|
requireContents = "";
|
||||||
pluginContents = "";
|
|
||||||
pluginBuildFileContents = "";
|
|
||||||
includeRequire = false;
|
includeRequire = false;
|
||||||
if ("includeRequire" in module) {
|
if ("includeRequire" in module) {
|
||||||
includeRequire = module.includeRequire;
|
includeRequire = module.includeRequire;
|
||||||
|
@ -551,25 +580,6 @@ var build, buildBaseConfig;
|
||||||
buildFileContents += "require.js\n";
|
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 there was an existing file with require in it, hoist to the top.
|
||||||
if (!includeRequire && layer.existingRequireUrl) {
|
if (!includeRequire && layer.existingRequireUrl) {
|
||||||
reqIndex = layer.buildFilePaths.indexOf(layer.existingRequireUrl);
|
reqIndex = layer.buildFilePaths.indexOf(layer.existingRequireUrl);
|
||||||
|
@ -584,41 +594,46 @@ var build, buildBaseConfig;
|
||||||
for (i = 0; (path = layer.buildFilePaths[i]); i++) {
|
for (i = 0; (path = layer.buildFilePaths[i]); i++) {
|
||||||
moduleName = layer.buildFileToModule[path];
|
moduleName = layer.buildFileToModule[path];
|
||||||
|
|
||||||
//Add the contents but remove any pragmas.
|
//Figure out if the module is a result of a build plugin, and if so,
|
||||||
currContents = pragma.process(path, fileUtil.readFile(path), config);
|
//then delegate to that plugin.
|
||||||
|
parts = context.makeModuleMap(moduleName);
|
||||||
//If anonymous module, insert the module name.
|
builder = parts.prefix && require.pluginBuilders[parts.prefix];
|
||||||
currContents = currContents.replace(anonDefRegExp, function (match, suffix) {
|
if (builder) {
|
||||||
layer.modulesWithNames[moduleName] = true;
|
if (builder.write) {
|
||||||
|
builder.write(parts.prefix, parts.name, function (input) {
|
||||||
//Look for CommonJS require calls inside the function if this is
|
fileContents += input;
|
||||||
//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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} 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 anonymous module, insert the module name.
|
||||||
if (require.s.contexts._.defPlugin[moduleName]) {
|
currContents = currContents.replace(anonDefRegExp, function (match, callName, possibleComment, suffix) {
|
||||||
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.
|
|
||||||
layer.modulesWithNames[moduleName] = true;
|
layer.modulesWithNames[moduleName] = true;
|
||||||
}
|
|
||||||
|
|
||||||
return "require.def('" + moduleName + "'," +
|
//Look for CommonJS require calls inside the function if this is
|
||||||
(deps ? ('[' + deps.toString() + '],') : '') +
|
//an anonymous define/require.def call that just has a function registered.
|
||||||
suffix;
|
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";
|
buildFileContents += path.replace(config.dir, "") + "\n";
|
||||||
//Some files may not have declared a require module, and if so,
|
//Some files may not have declared a require module, and if so,
|
||||||
|
@ -626,22 +641,12 @@ var build, buildBaseConfig;
|
||||||
//after the module is processed.
|
//after the module is processed.
|
||||||
//If we have a name, but no defined module, then add in the placeholder.
|
//If we have a name, but no defined module, then add in the placeholder.
|
||||||
if (moduleName && !layer.modulesWithNames[moduleName] && !config.skipModuleInsertion) {
|
if (moduleName && !layer.modulesWithNames[moduleName] && !config.skipModuleInsertion) {
|
||||||
fileContents += 'require.def("' + moduleName + '", function(){});\n';
|
fileContents += 'define("' + 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 = "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add the require file contents to the head of the file.
|
//Add the require file contents to the head of the file.
|
||||||
fileContents = (requireContents ? requireContents + "\n" : "") +
|
fileContents = (requireContents ? requireContents + "\n" : "") +
|
||||||
(pluginContents ? pluginContents + "\n" : "") +
|
|
||||||
fileContents;
|
fileContents;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
* @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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @license RequireJS Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
|
* @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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ var commonJs = {
|
||||||
|
|
||||||
//Get list of files to convert.
|
//Get list of files to convert.
|
||||||
fileList = fileUtil.getFilteredFileList(commonJsPath, /\w/, true);
|
fileList = fileUtil.getFilteredFileList(commonJsPath, /\w/, true);
|
||||||
|
|
||||||
//Normalize on front slashes and make sure the paths do not end in a slash.
|
//Normalize on front slashes and make sure the paths do not end in a slash.
|
||||||
commonJsPath = commonJsPath.replace(/\\/g, "/");
|
commonJsPath = commonJsPath.replace(/\\/g, "/");
|
||||||
savePath = savePath.replace(/\\/g, "/");
|
savePath = savePath.replace(/\\/g, "/");
|
||||||
|
@ -60,7 +60,7 @@ var commonJs = {
|
||||||
//Handle JS files.
|
//Handle JS files.
|
||||||
if (jsFileRegExp.test(fileName)) {
|
if (jsFileRegExp.test(fileName)) {
|
||||||
moduleName = fileName.replace(commonJsPath + "/", "").replace(/\.js$/, "");
|
moduleName = fileName.replace(commonJsPath + "/", "").replace(/\.js$/, "");
|
||||||
|
|
||||||
fileContents = fileUtil.readFile(fileName);
|
fileContents = fileUtil.readFile(fileName);
|
||||||
fileContents = commonJs.convert(prefix + moduleName, fileName, fileContents);
|
fileContents = commonJs.convert(prefix + moduleName, fileName, fileContents);
|
||||||
fileUtil.saveUtf8File(convertedFileName, fileContents);
|
fileUtil.saveUtf8File(convertedFileName, fileContents);
|
||||||
|
@ -77,10 +77,10 @@ var commonJs = {
|
||||||
* Rhino is available, otherwise a cruder regexp is used. If the regexp
|
* Rhino is available, otherwise a cruder regexp is used. If the regexp
|
||||||
* is used, then the contents may not be executable, but hopefully good
|
* is used, then the contents may not be executable, but hopefully good
|
||||||
* enough to use to find require() calls.
|
* enough to use to find require() calls.
|
||||||
*
|
*
|
||||||
* @param {String} fileContents
|
* @param {String} fileContents
|
||||||
* @param {String} fileName mostly used for informative reasons if an error.
|
* @param {String} fileName mostly used for informative reasons if an error.
|
||||||
*
|
*
|
||||||
* @returns {String} a string of JS with comments removed.
|
* @returns {String} a string of JS with comments removed.
|
||||||
*/
|
*/
|
||||||
removeComments: function (fileContents, fileName) {
|
removeComments: function (fileContents, fileName) {
|
||||||
|
@ -98,7 +98,7 @@ var commonJs = {
|
||||||
* Regexp for testing if there is already a require.def call in the file,
|
* Regexp for testing if there is already a require.def call in the file,
|
||||||
* in which case do not try to convert it.
|
* 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(){})
|
* Regexp for testing if there is a require([]) or require(function(){})
|
||||||
|
@ -110,22 +110,24 @@ var commonJs = {
|
||||||
* Does the actual file conversion.
|
* Does the actual file conversion.
|
||||||
*
|
*
|
||||||
* @param {String} moduleName the name of the module to use for the
|
* @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} fileName the name of the file.
|
||||||
*
|
*
|
||||||
* @param {String} fileContents the contents of a 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
|
* @returns {String} the converted contents
|
||||||
*/
|
*/
|
||||||
convert: function (moduleName, fileName, fileContents) {
|
convert: function (moduleName, fileName, fileContents, skipDeps) {
|
||||||
//Strip out comments.
|
//Strip out comments.
|
||||||
if (commonJs.useLog) {
|
|
||||||
logger.trace("fileName: " + fileName);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
var i, deps = [], depName, origDepName, part, pathConverted = {},
|
var deps = [], depName, match,
|
||||||
prop, reqRegExp, match,
|
|
||||||
//Remove comments
|
//Remove comments
|
||||||
tempContents = commonJs.removeComments(fileContents, fileName),
|
tempContents = commonJs.removeComments(fileContents, fileName),
|
||||||
baseName = moduleName.split("/");
|
baseName = moduleName.split("/");
|
||||||
|
@ -137,24 +139,26 @@ var commonJs = {
|
||||||
|
|
||||||
//Set baseName to be one directory higher than moduleName.
|
//Set baseName to be one directory higher than moduleName.
|
||||||
baseName.pop();
|
baseName.pop();
|
||||||
|
|
||||||
//Reset the regexp to start at beginning of file. Do this
|
//Reset the regexp to start at beginning of file. Do this
|
||||||
//since the regexp is reused across files.
|
//since the regexp is reused across files.
|
||||||
commonJs.depRegExp.lastIndex = 0;
|
commonJs.depRegExp.lastIndex = 0;
|
||||||
|
|
||||||
//Find dependencies in the code that was not in comments.
|
if (!skipDeps) {
|
||||||
while ((match = commonJs.depRegExp.exec(tempContents))) {
|
//Find dependencies in the code that was not in comments.
|
||||||
depName = match[1];
|
while ((match = commonJs.depRegExp.exec(tempContents))) {
|
||||||
if (commonJs.useLog) {
|
depName = match[1];
|
||||||
logger.trace(" " + depName);
|
if (commonJs.useLog) {
|
||||||
}
|
logger.trace(" " + depName);
|
||||||
if (depName) {
|
}
|
||||||
deps.push('"' + depName + '"');
|
if (depName) {
|
||||||
|
deps.push('"' + depName + '"');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Construct the wrapper boilerplate.
|
//Construct the wrapper boilerplate.
|
||||||
fileContents = 'require.def(["require", "exports", "module"' +
|
fileContents = 'define(["require", "exports", "module"' +
|
||||||
(deps.length ? ', ' + deps.join(",") : '') + '], ' +
|
(deps.length ? ', ' + deps.join(",") : '') + '], ' +
|
||||||
'function(require, exports, module) {\n' +
|
'function(require, exports, module) {\n' +
|
||||||
(commonJs.logConverted ? 'global._requirejs_logger.trace("Evaluating module: ' + moduleName + '");\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.
|
* @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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
//Helper functions to deal with file I/O.
|
//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) {
|
fileUtil.getFilteredFileList = function (/*String*/startDir, /*RegExp*/regExpFilters, /*boolean?*/makeUnixPaths, /*boolean?*/startDirIsJavaObject) {
|
||||||
//summary: Recurses startDir and finds matches to the files that match regExpFilters.include
|
//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 do not match regExpFilters.exclude. Or just one regexp can be passed in for regExpFilters,
|
||||||
//and it will be treated as the "include" case.
|
//and it will be treated as the "include" case.
|
||||||
//Ignores files/directories that start with a period (.).
|
//Ignores files/directories that start with a period (.).
|
||||||
var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
|
var files = [], topDir, regExpInclude, regExpExclude, dirFileArray,
|
||||||
i, file, filePath, ok, dirFiles;
|
i, file, filePath, ok, dirFiles;
|
||||||
|
|
||||||
topDir = startDir;
|
topDir = startDir;
|
||||||
if (!startDirIsJavaObject) {
|
if (!startDirIsJavaObject) {
|
||||||
topDir = new java.io.File(startDir);
|
topDir = new java.io.File(startDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
regExpInclude = regExpFilters.include || regExpFilters;
|
regExpInclude = regExpFilters.include || regExpFilters;
|
||||||
regExpExclude = regExpFilters.exclude || null;
|
regExpExclude = regExpFilters.exclude || null;
|
||||||
|
|
||||||
if (topDir.exists()) {
|
if (topDir.exists()) {
|
||||||
dirFileArray = topDir.listFiles();
|
dirFileArray = topDir.listFiles();
|
||||||
for (i = 0; i < dirFileArray.length; i++) {
|
for (i = 0; i < dirFileArray.length; i++) {
|
||||||
file = dirFileArray[i];
|
file = dirFileArray[i];
|
||||||
if (file.isFile()) {
|
if (file.isFile()) {
|
||||||
filePath = file.getPath();
|
filePath = file.getPath();
|
||||||
if (makeUnixPaths) {
|
if (makeUnixPaths) {
|
||||||
//Make sure we have a JS string.
|
//Make sure we have a JS string.
|
||||||
filePath = String(filePath);
|
filePath = String(filePath);
|
||||||
if (filePath.indexOf("/") === -1) {
|
if (filePath.indexOf("/") === -1) {
|
||||||
filePath = filePath.replace(/\\/g, "/");
|
filePath = filePath.replace(/\\/g, "/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = true;
|
|
||||||
if (regExpInclude) {
|
|
||||||
ok = filePath.match(regExpInclude);
|
|
||||||
}
|
|
||||||
if (ok && regExpExclude) {
|
|
||||||
ok = !filePath.match(regExpExclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok && !file.getName().match(/^\./)) {
|
ok = true;
|
||||||
files.push(filePath);
|
if (regExpInclude) {
|
||||||
}
|
ok = filePath.match(regExpInclude);
|
||||||
} else if (file.isDirectory() && !file.getName().match(/^\./)) {
|
}
|
||||||
dirFiles = this.getFilteredFileList(file, regExpFilters, makeUnixPaths, true);
|
if (ok && regExpExclude) {
|
||||||
files.push.apply(files, dirFiles);
|
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) {
|
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
|
//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.
|
//file should be copied. Returns a list file name strings of the destinations that were copied.
|
||||||
regExpFilter |= /\w/;
|
regExpFilter = regExpFilter || /\w/;
|
||||||
|
|
||||||
var fileNames = fileUtil.getFilteredFileList(srcDir, regExpFilter, true),
|
var fileNames = fileUtil.getFilteredFileList(srcDir, regExpFilter, true),
|
||||||
copiedFiles = [], i, srcFileName, destFileName;
|
copiedFiles = [], i, srcFileName, destFileName;
|
||||||
|
|
||||||
for (i = 0; i < fileNames.length; i++) {
|
for (i = 0; i < fileNames.length; i++) {
|
||||||
srcFileName = fileNames[i];
|
srcFileName = fileNames[i];
|
||||||
destFileName = srcFileName.replace(srcDir, destDir);
|
destFileName = srcFileName.replace(srcDir, destDir);
|
||||||
|
|
||||||
if (fileUtil.copyFile(srcFileName, destFileName, onlyCopyNew)) {
|
if (fileUtil.copyFile(srcFileName, destFileName, onlyCopyNew)) {
|
||||||
copiedFiles.push(destFileName);
|
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) {
|
fileUtil.copyFile = function (/*String*/srcFileName, /*String*/destFileName, /*boolean?*/onlyCopyNew) {
|
||||||
//summary: copies srcFileName to destFileName. If onlyCopyNew is set, it only copies the file if
|
//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.
|
//srcFileName is newer than destFileName. Returns a boolean indicating if the copy occurred.
|
||||||
var destFile = new java.io.File(destFileName), srcFile, parentDir,
|
var destFile = new java.io.File(destFileName), srcFile, parentDir,
|
||||||
srcChannel, destChannel;
|
srcChannel, destChannel;
|
||||||
|
|
||||||
//logger.trace("Src filename: " + srcFileName);
|
//logger.trace("Src filename: " + srcFileName);
|
||||||
//logger.trace("Dest filename: " + destFileName);
|
//logger.trace("Dest filename: " + destFileName);
|
||||||
|
|
||||||
//If onlyCopyNew is true, then compare dates and only copy if the src is newer
|
//If onlyCopyNew is true, then compare dates and only copy if the src is newer
|
||||||
//than dest.
|
//than dest.
|
||||||
if (onlyCopyNew) {
|
if (onlyCopyNew) {
|
||||||
srcFile = new java.io.File(srcFileName);
|
srcFile = new java.io.File(srcFileName);
|
||||||
if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) {
|
if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified()) {
|
||||||
return false; //Boolean
|
return false; //Boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Make sure destination dir exists.
|
//Make sure destination dir exists.
|
||||||
parentDir = destFile.getParentFile();
|
parentDir = destFile.getParentFile();
|
||||||
if (!parentDir.exists()) {
|
if (!parentDir.exists()) {
|
||||||
if (!parentDir.mkdirs()) {
|
if (!parentDir.mkdirs()) {
|
||||||
throw "Could not create directory: " + parentDir.getAbsolutePath();
|
throw "Could not create directory: " + parentDir.getAbsolutePath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Java's version of copy file.
|
//Java's version of copy file.
|
||||||
srcChannel = new java.io.FileInputStream(srcFileName).getChannel();
|
srcChannel = new java.io.FileInputStream(srcFileName).getChannel();
|
||||||
destChannel = new java.io.FileOutputStream(destFileName).getChannel();
|
destChannel = new java.io.FileOutputStream(destFileName).getChannel();
|
||||||
destChannel.transferFrom(srcChannel, 0, srcChannel.size());
|
destChannel.transferFrom(srcChannel, 0, srcChannel.size());
|
||||||
srcChannel.close();
|
srcChannel.close();
|
||||||
destChannel.close();
|
destChannel.close();
|
||||||
|
|
||||||
return true; //Boolean
|
return true; //Boolean
|
||||||
};
|
};
|
||||||
|
|
||||||
fileUtil.readFile = function (/*String*/path, /*String?*/encoding) {
|
fileUtil.readFile = function (/*String*/path, /*String?*/encoding) {
|
||||||
//summary: reads a file and returns a string
|
//summary: reads a file and returns a string
|
||||||
encoding = encoding || "utf-8";
|
encoding = encoding || "utf-8";
|
||||||
var file = new java.io.File(path),
|
var file = new java.io.File(path),
|
||||||
lineSeparator = fileUtil.getLineSeparator(),
|
lineSeparator = fileUtil.getLineSeparator(),
|
||||||
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
|
input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
|
||||||
stringBuffer, line;
|
stringBuffer, line;
|
||||||
try {
|
try {
|
||||||
stringBuffer = new java.lang.StringBuffer();
|
stringBuffer = new java.lang.StringBuffer();
|
||||||
line = input.readLine();
|
line = input.readLine();
|
||||||
|
|
||||||
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
|
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
|
||||||
// http://www.unicode.org/faq/utf_bom.html
|
// 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:
|
// 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
|
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
|
||||||
if (line && line.length() && line.charAt(0) === 0xfeff) {
|
if (line && line.length() && line.charAt(0) === 0xfeff) {
|
||||||
// Eat the BOM, since we've already found the encoding on this file,
|
// 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
|
// and we plan to concatenating this buffer with others; the BOM should
|
||||||
// only appear at the top of a file.
|
// only appear at the top of a file.
|
||||||
line = line.substring(1);
|
line = line.substring(1);
|
||||||
}
|
}
|
||||||
while (line !== null) {
|
while (line !== null) {
|
||||||
stringBuffer.append(line);
|
stringBuffer.append(line);
|
||||||
stringBuffer.append(lineSeparator);
|
stringBuffer.append(lineSeparator);
|
||||||
line = input.readLine();
|
line = input.readLine();
|
||||||
}
|
}
|
||||||
//Make sure we return a JavaScript string and not a Java string.
|
//Make sure we return a JavaScript string and not a Java string.
|
||||||
return String(stringBuffer.toString()); //String
|
return String(stringBuffer.toString()); //String
|
||||||
} finally {
|
} finally {
|
||||||
input.close();
|
input.close();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fileUtil.saveUtf8File = function (/*String*/fileName, /*String*/fileContents) {
|
fileUtil.saveUtf8File = function (/*String*/fileName, /*String*/fileContents) {
|
||||||
//summary: saves a file using UTF-8 encoding.
|
//summary: saves a file using UTF-8 encoding.
|
||||||
fileUtil.saveFile(fileName, fileContents, "utf-8");
|
fileUtil.saveFile(fileName, fileContents, "utf-8");
|
||||||
};
|
};
|
||||||
|
|
||||||
fileUtil.saveFile = function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
|
fileUtil.saveFile = function (/*String*/fileName, /*String*/fileContents, /*String?*/encoding) {
|
||||||
//summary: saves a file.
|
//summary: saves a file.
|
||||||
var outFile = new java.io.File(fileName), outWriter, parentDir, os;
|
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
os = new java.io.BufferedWriter(outWriter);
|
parentDir = outFile.getAbsoluteFile().getParentFile();
|
||||||
try {
|
if (!parentDir.exists()) {
|
||||||
os.write(fileContents);
|
if (!parentDir.mkdirs()) {
|
||||||
} finally {
|
throw "Could not create directory: " + parentDir.getAbsolutePath();
|
||||||
os.close();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
fileUtil.deleteFile = function (/*String*/fileName) {
|
||||||
//summary: deletes a file or directory if it exists.
|
//summary: deletes a file or directory if it exists.
|
||||||
var file = new java.io.File(fileName), files, i;
|
var file = new java.io.File(fileName), files, i;
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
files = file.listFiles();
|
files = file.listFiles();
|
||||||
for (i = 0; i < files.length; i++) {
|
for (i = 0; i < files.length; i++) {
|
||||||
this.deleteFile(files[i]);
|
this.deleteFile(files[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file["delete"]();
|
file["delete"]();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
* @license 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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @license RequireJS Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
* @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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
var logger = {
|
var logger = {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/**
|
/**
|
||||||
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
* @license 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
|
* 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,
|
/*global require: false, java: false, Packages: false, logger: false, fileUtil: false,
|
||||||
readFile: false, lang: false */
|
readFile: false, lang: false */
|
||||||
|
|
||||||
|
@ -14,8 +14,6 @@ var optimize;
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
var JSSourceFilefromCode,
|
var JSSourceFilefromCode,
|
||||||
textDepRegExp = /["'](text)\!([^"']+)["']/g,
|
|
||||||
relativeDefRegExp = /require\s*\.\s*def\s*\(\s*['"]([^'"]+)['"]/g,
|
|
||||||
cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/g,
|
cssImportRegExp = /\@import\s+(url\()?\s*([^);]+)\s*(\))?([\w, ]*)(;)?/g,
|
||||||
cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g;
|
cssUrlRegExp = /\url\(\s*([^\)]+)\s*\)?/g;
|
||||||
|
|
||||||
|
@ -30,18 +28,6 @@ var optimize;
|
||||||
return JSSourceFilefromCode.invoke(null, [filename, content]);
|
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.
|
* 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,
|
* 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")) {
|
if (mediaTypes && ((mediaTypes.replace(/^\s\s*/, '').replace(/\s\s*$/, '')) !== "all")) {
|
||||||
return fullMatch;
|
return fullMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
importFileName = cleanCssUrlQuotes(importFileName);
|
importFileName = cleanCssUrlQuotes(importFileName);
|
||||||
|
|
||||||
//Ignore the file import if it is part of an ignore list.
|
//Ignore the file import if it is part of an ignore list.
|
||||||
if (cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") !== -1) {
|
if (cssImportIgnore && cssImportIgnore.indexOf(importFileName + ",") !== -1) {
|
||||||
return fullMatch;
|
return fullMatch;
|
||||||
|
@ -95,7 +81,7 @@ var optimize;
|
||||||
|
|
||||||
//Make sure we have a unix path for the rest of the operation.
|
//Make sure we have a unix path for the rest of the operation.
|
||||||
importFileName = importFileName.replace(lang.backSlashRegExp, "/");
|
importFileName = importFileName.replace(lang.backSlashRegExp, "/");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//if a relative path, then tack on the filePath.
|
//if a relative path, then tack on the filePath.
|
||||||
//If it is not a relative path, then the readFile below will fail,
|
//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) {
|
importContents = importContents.replace(cssUrlRegExp, function (fullMatch, urlMatch) {
|
||||||
fixedUrlMatch = cleanCssUrlQuotes(urlMatch);
|
fixedUrlMatch = cleanCssUrlQuotes(urlMatch);
|
||||||
fixedUrlMatch = fixedUrlMatch.replace(lang.backSlashRegExp, "/");
|
fixedUrlMatch = fixedUrlMatch.replace(lang.backSlashRegExp, "/");
|
||||||
|
|
||||||
//Only do the work for relative URLs. Skip things that start with / or have
|
//Only do the work for relative URLs. Skip things that start with / or have
|
||||||
//a protocol.
|
//a protocol.
|
||||||
colonIndex = fixedUrlMatch.indexOf(":");
|
colonIndex = fixedUrlMatch.indexOf(":");
|
||||||
|
@ -141,10 +127,10 @@ var optimize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "url(" + parts.join("/") + ")";
|
return "url(" + parts.join("/") + ")";
|
||||||
});
|
});
|
||||||
|
|
||||||
return importContents;
|
return importContents;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.trace(fileName + "\n Cannot inline css import, skipping: " + importFileName);
|
logger.trace(fileName + "\n Cannot inline css import, skipping: " + importFileName);
|
||||||
|
@ -154,101 +140,38 @@ var optimize;
|
||||||
}
|
}
|
||||||
|
|
||||||
optimize = {
|
optimize = {
|
||||||
closure: function (fileName, fileContents, keepLines) {
|
closure: function (fileName, fileContents, keepLines, config) {
|
||||||
|
config = config || {};
|
||||||
var jscomp = Packages.com.google.javascript.jscomp,
|
var jscomp = Packages.com.google.javascript.jscomp,
|
||||||
flags = Packages.com.google.common.flags,
|
flags = Packages.com.google.common.flags,
|
||||||
//Fake extern
|
//Fake extern
|
||||||
externSourceFile = closurefromCode("fakeextern.js", " "),
|
externSourceFile = closurefromCode("fakeextern.js", " "),
|
||||||
//Set up source input
|
//Set up source input
|
||||||
jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
||||||
options, FLAG_compilation_level, compiler,
|
options, option, FLAG_compilation_level, compiler,
|
||||||
Compiler = Packages.com.google.javascript.jscomp.Compiler;
|
Compiler = Packages.com.google.javascript.jscomp.Compiler;
|
||||||
|
|
||||||
logger.trace("Minifying file: " + fileName);
|
logger.trace("Minifying file: " + fileName);
|
||||||
|
|
||||||
//Set up options
|
//Set up options
|
||||||
options = new jscomp.CompilerOptions();
|
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);
|
FLAG_compilation_level.get().setOptionsForCompilationLevel(options);
|
||||||
|
|
||||||
//Trigger the compiler
|
//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 = new Compiler();
|
||||||
compiler.compile(externSourceFile, jsSourceFile, options);
|
compiler.compile(externSourceFile, jsSourceFile, options);
|
||||||
return compiler.toSource();
|
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) + "'";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -265,24 +188,14 @@ var optimize;
|
||||||
var doClosure = (config.optimize + "").indexOf("closure") === 0,
|
var doClosure = (config.optimize + "").indexOf("closure") === 0,
|
||||||
fileContents;
|
fileContents;
|
||||||
|
|
||||||
if (config.inlineText && !optimize.textLoaded) {
|
|
||||||
//Make sure text extension is loaded.
|
|
||||||
require(["require/text"]);
|
|
||||||
optimize.textLoaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fileContents = fileUtil.readFile(fileName);
|
fileContents = fileUtil.readFile(fileName);
|
||||||
|
|
||||||
//Inline text files.
|
|
||||||
if (config.inlineText) {
|
|
||||||
fileContents = optimize.inlineText(fileName, fileContents);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Optimize the JS files if asked.
|
//Optimize the JS files if asked.
|
||||||
if (doClosure) {
|
if (doClosure) {
|
||||||
fileContents = optimize.closure(fileName,
|
fileContents = optimize.closure(fileName,
|
||||||
fileContents,
|
fileContents,
|
||||||
(config.optimize.indexOf(".keepLines") !== -1));
|
(config.optimize.indexOf(".keepLines") !== -1),
|
||||||
|
config.closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
fileUtil.saveUtf8File(outFileName, fileContents);
|
fileUtil.saveUtf8File(outFileName, fileContents);
|
||||||
|
@ -341,7 +254,7 @@ var optimize;
|
||||||
*/
|
*/
|
||||||
css: function (startDir, config) {
|
css: function (startDir, config) {
|
||||||
if (config.optimizeCss.indexOf("standard") !== -1) {
|
if (config.optimizeCss.indexOf("standard") !== -1) {
|
||||||
var i, fileName, startIndex, endIndex, originalFileContents, fileContents,
|
var i, fileName,
|
||||||
fileList = fileUtil.getFilteredFileList(startDir, /\.css$/, true);
|
fileList = fileUtil.getFilteredFileList(startDir, /\.css$/, true);
|
||||||
if (fileList) {
|
if (fileList) {
|
||||||
for (i = 0; i < fileList.length; i++) {
|
for (i = 0; i < fileList.length; i++) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
* @license 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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -47,6 +47,26 @@ var parse;
|
||||||
return String(node.getString());
|
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)
|
* Validates a node as being an object literal (like for i18n bundles)
|
||||||
* or an array literal with just string members.
|
* or an array literal with just string members.
|
||||||
|
@ -60,7 +80,7 @@ var parse;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Dependencies can be an object literal or an array.
|
//Dependencies can be an object literal or an array.
|
||||||
if (type !== ARRAYLIT) {
|
if (type !== ARRAYLIT) {
|
||||||
return false;
|
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.
|
* calls as part of one JavaScript source string.
|
||||||
* @param {String} fileName
|
* @param {String} fileName
|
||||||
* @param {String} fileContents
|
* @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.
|
* calls are found.
|
||||||
*/
|
*/
|
||||||
parse = function (fileName, fileContents) {
|
parse = function (fileName, fileContents) {
|
||||||
//Set up source input
|
//Set up source input
|
||||||
var matches = [], result = null,
|
var matches = [], result = null,
|
||||||
jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
||||||
astRoot = compiler.parse(jsSourceFile);
|
astRoot = compilerParse(jsSourceFile, fileName);
|
||||||
|
|
||||||
parse.recurse(astRoot, matches);
|
parse.recurse(astRoot, matches);
|
||||||
|
|
||||||
|
@ -109,7 +129,7 @@ var parse;
|
||||||
matches.push(parsed);
|
matches.push(parsed);
|
||||||
}
|
}
|
||||||
parse.recurse(node, matches);
|
parse.recurse(node, matches);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -120,15 +140,15 @@ var parse;
|
||||||
*/
|
*/
|
||||||
parse.definesRequire = function (fileName, fileContents) {
|
parse.definesRequire = function (fileName, fileContents) {
|
||||||
var jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
var jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
||||||
astRoot = compiler.parse(jsSourceFile);
|
astRoot = compilerParse(jsSourceFile, fileName);
|
||||||
|
|
||||||
return parse.nodeHasRequire(astRoot);
|
return parse.nodeHasRequire(astRoot);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds require("") calls inside a CommonJS anonymous module wrapped in a
|
* Finds require("") calls inside a CommonJS anonymous module wrapped in a
|
||||||
* require.def(function(require, exports, module){}) wrapper. These dependencies
|
* define/require.def(function(require, exports, module){}) wrapper. These dependencies
|
||||||
* will be added to a modified require.def call that lists the dependencies
|
* will be added to a modified define() call that lists the dependencies
|
||||||
* on the outside of the function.
|
* on the outside of the function.
|
||||||
* @param {String} fileName
|
* @param {String} fileName
|
||||||
* @param {String} fileContents
|
* @param {String} fileContents
|
||||||
|
@ -137,10 +157,10 @@ var parse;
|
||||||
*/
|
*/
|
||||||
parse.getAnonDeps = function (fileName, fileContents) {
|
parse.getAnonDeps = function (fileName, fileContents) {
|
||||||
var jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
var jsSourceFile = closurefromCode(String(fileName), String(fileContents)),
|
||||||
astRoot = compiler.parse(jsSourceFile),
|
astRoot = compilerParse(jsSourceFile, fileName),
|
||||||
deps = [],
|
deps = [],
|
||||||
defFunc = parse.findAnonRequireDefCallback(astRoot);
|
defFunc = parse.findAnonRequireDefCallback(astRoot);
|
||||||
|
|
||||||
//Now look inside the def call's function for require calls.
|
//Now look inside the def call's function for require calls.
|
||||||
if (defFunc) {
|
if (defFunc) {
|
||||||
parse.findRequireDepNames(defFunc, deps);
|
parse.findRequireDepNames(defFunc, deps);
|
||||||
|
@ -174,6 +194,16 @@ var parse;
|
||||||
return func;
|
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
|
//Check child nodes
|
||||||
|
@ -253,28 +283,95 @@ var parse;
|
||||||
return false;
|
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
|
* @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.
|
* Otherwise null.
|
||||||
*/
|
*/
|
||||||
parse.parseNode = function (node) {
|
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) {
|
if (node.getType() === EXPR_RESULT && node.getFirstChild().getType() === CALL) {
|
||||||
call = node.getFirstChild();
|
call = node.getFirstChild();
|
||||||
|
|
||||||
if (call.getFirstChild().getType() === NAME &&
|
if (call.getFirstChild().getType() === NAME &&
|
||||||
nodeString(call.getFirstChild()) === "require") {
|
nodeString(call.getFirstChild()) === "require") {
|
||||||
|
|
||||||
//It is a plain require() call.
|
//It is a plain require() call.
|
||||||
deps = call.getChildAtIndex(1);
|
config = call.getChildAtIndex(1);
|
||||||
if (!validateDeps(deps)) {
|
deps = call.getChildAtIndex(2);
|
||||||
|
if (config.getType() === ARRAYLIT) {
|
||||||
|
deps = config;
|
||||||
|
config = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deps || !validateDeps(deps)) {
|
||||||
return null;
|
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 &&
|
} else if (call.getFirstChild().getType() === GETPROP &&
|
||||||
call.getFirstChild().getFirstChild().getType() === NAME &&
|
call.getFirstChild().getFirstChild().getType() === NAME &&
|
||||||
|
@ -289,21 +386,7 @@ var parse;
|
||||||
name = call.getChildAtIndex(1);
|
name = call.getChildAtIndex(1);
|
||||||
deps = call.getChildAtIndex(2);
|
deps = call.getChildAtIndex(2);
|
||||||
|
|
||||||
//If name is an array, it means it is an anonymous module,
|
return parse.callToString("define", null, name, deps);
|
||||||
//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);
|
|
||||||
} else if (methodName === "modify") {
|
} else if (methodName === "modify") {
|
||||||
|
|
||||||
//A require.modify() call
|
//A require.modify() call
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @license Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
* @license 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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
||||||
var pragma = {
|
var pragma = {
|
||||||
conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/,
|
conditionalRegExp: /(exclude|include)Start\s*\(\s*["'](\w+)["']\s*,(.*)\)/,
|
||||||
useStrictRegExp: /['"]use strict['"];/g,
|
useStrictRegExp: /['"]use strict['"];/g,
|
||||||
|
hasRegExp: /has\s*\(\s*['"]([^'"]+)['"]\)/g,
|
||||||
|
|
||||||
removeStrict: function (contents, config) {
|
removeStrict: function (contents, config) {
|
||||||
return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, '');
|
return config.useStrict ? contents : contents.replace(pragma.useStrictRegExp, '');
|
||||||
|
@ -27,11 +28,17 @@ var pragma = {
|
||||||
endMarkerIndex, shouldInclude, startLength, pragmas = config.pragmas,
|
endMarkerIndex, shouldInclude, startLength, pragmas = config.pragmas,
|
||||||
//Legacy arg defined to help in dojo conversion script. Remove later
|
//Legacy arg defined to help in dojo conversion script. Remove later
|
||||||
//when dojo no longer needs conversion:
|
//when dojo no longer needs conversion:
|
||||||
kwArgs = {
|
kwArgs = pragmas;
|
||||||
profileProperties: {
|
|
||||||
hostenvType: "browser"
|
//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 pragma work is not desired, skip it.
|
||||||
if (config.skipPragmas) {
|
if (config.skipPragmas) {
|
||||||
|
@ -44,10 +51,10 @@ var pragma = {
|
||||||
if (lineEndIndex === -1) {
|
if (lineEndIndex === -1) {
|
||||||
lineEndIndex = fileContents.length - 1;
|
lineEndIndex = fileContents.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Increment startIndex past the line so the next conditional search can be done.
|
//Increment startIndex past the line so the next conditional search can be done.
|
||||||
startIndex = lineEndIndex + 1;
|
startIndex = lineEndIndex + 1;
|
||||||
|
|
||||||
//Break apart the conditional.
|
//Break apart the conditional.
|
||||||
conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1);
|
conditionLine = fileContents.substring(foundIndex, lineEndIndex + 1);
|
||||||
matches = conditionLine.match(pragma.conditionalRegExp);
|
matches = conditionLine.match(pragma.conditionalRegExp);
|
||||||
|
@ -66,29 +73,29 @@ var pragma = {
|
||||||
conditionLine +
|
conditionLine +
|
||||||
" failed with this error: " + e;
|
" failed with this error: " + e;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Find the endpoint marker.
|
//Find the endpoint marker.
|
||||||
endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g");
|
endRegExp = new RegExp('\\/\\/\\>\\>\\s*' + type + 'End\\(\\s*[\'"]' + marker + '[\'"]\\s*\\)', "g");
|
||||||
endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length));
|
endMatches = endRegExp.exec(fileContents.substring(startIndex, fileContents.length));
|
||||||
if (endMatches) {
|
if (endMatches) {
|
||||||
endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length;
|
endMarkerIndex = startIndex + endRegExp.lastIndex - endMatches[0].length;
|
||||||
|
|
||||||
//Find the next line return based on the match position.
|
//Find the next line return based on the match position.
|
||||||
lineEndIndex = fileContents.indexOf("\n", endMarkerIndex);
|
lineEndIndex = fileContents.indexOf("\n", endMarkerIndex);
|
||||||
if (lineEndIndex === -1) {
|
if (lineEndIndex === -1) {
|
||||||
lineEndIndex = fileContents.length - 1;
|
lineEndIndex = fileContents.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Should we include the segment?
|
//Should we include the segment?
|
||||||
shouldInclude = ((type === "exclude" && !isTrue) || (type === "include" && isTrue));
|
shouldInclude = ((type === "exclude" && !isTrue) || (type === "include" && isTrue));
|
||||||
|
|
||||||
//Remove the conditional comments, and optionally remove the content inside
|
//Remove the conditional comments, and optionally remove the content inside
|
||||||
//the conditional comments.
|
//the conditional comments.
|
||||||
startLength = startIndex - foundIndex;
|
startLength = startIndex - foundIndex;
|
||||||
fileContents = fileContents.substring(0, foundIndex) +
|
fileContents = fileContents.substring(0, foundIndex) +
|
||||||
(shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "") +
|
(shouldInclude ? fileContents.substring(startIndex, endMarkerIndex) : "") +
|
||||||
fileContents.substring(lineEndIndex + 1, fileContents.length);
|
fileContents.substring(lineEndIndex + 1, fileContents.length);
|
||||||
|
|
||||||
//Move startIndex to foundIndex, since that is the new position in the file
|
//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.
|
//where we need to look for more conditionals in the next while loop pass.
|
||||||
startIndex = foundIndex;
|
startIndex = foundIndex;
|
||||||
|
@ -97,7 +104,7 @@ var pragma = {
|
||||||
fileName +
|
fileName +
|
||||||
". Cannot find end marker for conditional comment: " +
|
". Cannot find end marker for conditional comment: " +
|
||||||
conditionLine;
|
conditionLine;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* @license RequireJS Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
|
* @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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
|
@ -9,12 +9,13 @@
|
||||||
|
|
||||||
/*jslint nomen: false, plusplus: false, regexp: false */
|
/*jslint nomen: false, plusplus: false, regexp: false */
|
||||||
/*global load: false, require: false, logger: false, setTimeout: true,
|
/*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";
|
"use strict";
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
var layer,
|
var layer,
|
||||||
lineSeparator = java.lang.System.getProperty("line.separator"),
|
lineSeparator = java.lang.System.getProperty("line.separator"),
|
||||||
|
pluginBuilderRegExp = /(["']?)pluginBuilder(["']?)\s*[=\:]\s*["']([^'"\s]+)["']/,
|
||||||
oldDef;
|
oldDef;
|
||||||
|
|
||||||
//A file read function that can deal with BOMs
|
//A file read function that can deal with BOMs
|
||||||
|
@ -26,10 +27,10 @@
|
||||||
try {
|
try {
|
||||||
stringBuffer = new java.lang.StringBuffer();
|
stringBuffer = new java.lang.StringBuffer();
|
||||||
line = input.readLine();
|
line = input.readLine();
|
||||||
|
|
||||||
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
|
// Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
|
||||||
// http://www.unicode.org/faq/utf_bom.html
|
// 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:
|
// 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
|
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
|
||||||
if (line && line.length() && line.charAt(0) === 0xfeff) {
|
if (line && line.length() && line.charAt(0) === 0xfeff) {
|
||||||
|
@ -53,7 +54,7 @@
|
||||||
/** Reset state for each build layer pass. */
|
/** Reset state for each build layer pass. */
|
||||||
require._buildReset = function () {
|
require._buildReset = function () {
|
||||||
//Clear up the existing context.
|
//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
|
//These variables are not contextName-aware since the build should
|
||||||
//only have one context.
|
//only have one context.
|
||||||
|
@ -77,8 +78,11 @@
|
||||||
*/
|
*/
|
||||||
require._isSupportedBuildUrl = function (url) {
|
require._isSupportedBuildUrl = function (url) {
|
||||||
//Ignore URLs with protocols or question marks, means either network
|
//Ignore URLs with protocols or question marks, means either network
|
||||||
//access is needed to fetch it or it is too dynamic.
|
//access is needed to fetch it or it is too dynamic. Note that
|
||||||
return url.indexOf(":") === -1 && url.indexOf("?") === -1;
|
//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
|
//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
|
//This function signature does not have to be exact, just match what we
|
||||||
//are looking for.
|
//are looking for.
|
||||||
require.def = function (name, obj) {
|
define = require.def = function (name, obj) {
|
||||||
if (typeof name === "string" && !require.isArray(obj) && !require.isFunction(obj)) {
|
if (typeof name === "string") {
|
||||||
layer.modulesWithNames[name] = true;
|
layer.modulesWithNames[name] = true;
|
||||||
}
|
}
|
||||||
return oldDef.apply(require, arguments);
|
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.
|
//Override load so that the file paths can be collected.
|
||||||
require.load = function (moduleName, contextName) {
|
require.load = function (context, moduleName, url) {
|
||||||
/*jslint evil: true */
|
/*jslint evil: true */
|
||||||
var url = require.nameToUrl(moduleName, null, contextName), map,
|
var isPlugin = false,
|
||||||
contents,
|
contents, pluginBuilderMatch, builderName;
|
||||||
context = require.s.contexts[contextName];
|
|
||||||
|
//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.loaded[moduleName] = false;
|
||||||
|
context.scriptCount += 1;
|
||||||
|
|
||||||
//Only handle urls that can be inlined, so that means avoiding some
|
//Only handle urls that can be inlined, so that means avoiding some
|
||||||
//URLs like ones that require network access or may be too dynamic,
|
//URLs like ones that require network access or may be too dynamic,
|
||||||
//like JSONP
|
//like JSONP
|
||||||
if (require._isSupportedBuildUrl(url)) {
|
if (require._isSupportedBuildUrl(url)) {
|
||||||
//Save the module name to path mapping.
|
//Save the module name to path and path to module name mappings.
|
||||||
map = layer.buildPathMap[moduleName] = url;
|
layer.buildPathMap[moduleName] = url;
|
||||||
|
layer.buildFileToModule[url] = moduleName;
|
||||||
|
|
||||||
//Load the file contents, process for conditionals, then
|
//Load the file contents, process for conditionals, then
|
||||||
//evaluate it.
|
//evaluate it.
|
||||||
contents = _readFile(url);
|
contents = _readFile(url);
|
||||||
contents = pragma.process(url, contents, context.config);
|
contents = pragma.process(url, contents, context.config);
|
||||||
|
|
||||||
//Find out if the file contains a require() definition. Need to know
|
//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,
|
//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.
|
//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)) {
|
if (!layer.existingRequireUrl && parse.definesRequire(url, contents)) {
|
||||||
layer.existingRequireUrl = url;
|
layer.existingRequireUrl = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Only eval complete contents if asked, or if it is a require extension.
|
if (moduleName in context.plugins) {
|
||||||
//Otherwise, treat the module as not safe for execution and parse out
|
//This is a loader plugin, check to see if it has a build extension,
|
||||||
//the require calls.
|
//otherwise the plugin will act as the plugin builder too.
|
||||||
if (!context.config.execModules && moduleName !== "require/text" && moduleName !== "require/i18n") {
|
pluginBuilderMatch = pluginBuilderRegExp.exec(contents);
|
||||||
//Only find the require parts with [] dependencies and
|
if (pluginBuilderMatch) {
|
||||||
//evaluate those. This path is useful when the code
|
//Load the plugin builder for the plugin contents.
|
||||||
//does not follow the strict require pattern of wrapping all
|
builderName = context.normalize(pluginBuilderMatch[3], moduleName);
|
||||||
//code in a require callback.
|
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);
|
contents = parse(url, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contents) {
|
if (contents) {
|
||||||
eval(contents);
|
eval(contents);
|
||||||
|
|
||||||
//Support anonymous modules.
|
//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.
|
//Mark the module loaded.
|
||||||
context.loaded[moduleName] = true;
|
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
|
//Override a method provided by require/text.js for loading text files as
|
||||||
|
@ -162,9 +207,12 @@
|
||||||
require.execCb = function (name, cb, args) {
|
require.execCb = function (name, cb, args) {
|
||||||
var url = name && layer.buildPathMap[name];
|
var url = name && layer.buildPathMap[name];
|
||||||
if (url && !layer.loadedFiles[url]) {
|
if (url && !layer.loadedFiles[url]) {
|
||||||
layer.buildFilePaths.push(url);
|
|
||||||
layer.loadedFiles[url] = true;
|
layer.loadedFiles[url] = true;
|
||||||
layer.modulesWithNames[name] = 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.
|
* @license RequireJS i18n 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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
/*jslint regexp: false, nomen: false, plusplus: false */
|
/*jslint regexp: false, nomen: false, plusplus: false */
|
||||||
/*global require: false, navigator: false */
|
/*global require: false, navigator: false, define: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,284 +42,101 @@
|
||||||
//nlsRegExp.exec("foo/bar/baz/nls/foo") gives:
|
//nlsRegExp.exec("foo/bar/baz/nls/foo") gives:
|
||||||
//["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
|
//["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
|
||||||
//so, if match[5] is blank, it means this is the top bundle definition.
|
//so, if match[5] is blank, it means this is the top bundle definition.
|
||||||
var nlsRegExp = /(^.*(^|\/)nls(\/|$))([^\/]*)\/?([^\/]*)/,
|
var nlsRegExp = /(^.*(^|\/)nls(\/|$))([^\/]*)\/?([^\/]*)/;
|
||||||
empty = {};
|
|
||||||
|
|
||||||
function getWaiting(name, context) {
|
//Helper function to avoid repeating code. Lots of arguments in the
|
||||||
var nlswAry = context.nlsWaiting;
|
//desire to stay functional and support RequireJS contexts without having
|
||||||
return nlswAry[name] ||
|
//to know about the RequireJS contexts.
|
||||||
//Push a new waiting object on the nlsWaiting array, but also put
|
function addPart(locale, master, needed, toLoad, prefix, suffix) {
|
||||||
//a shortcut lookup by name to the object on the array.
|
if (master[locale]) {
|
||||||
(nlswAry[name] = nlswAry[(nlswAry.push({ _name: name}) - 1)]);
|
needed.push(locale);
|
||||||
}
|
if (master[locale] === true || master[locale] === 1) {
|
||||||
|
toLoad.push(prefix + locale + '/' + suffix);
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//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({
|
function addIfExists(req, locale, toLoad, prefix, suffix) {
|
||||||
prefix: "i18n",
|
var fullName = prefix + locale + '/' + suffix;
|
||||||
|
if (require._fileExists(req.nameToUrl(fullName, null))) {
|
||||||
/**
|
toLoad.push(fullName);
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
define({
|
||||||
/**
|
/**
|
||||||
* Called when a dependency needs to be loaded.
|
* Called when a dependency needs to be loaded.
|
||||||
*/
|
*/
|
||||||
load: function (name, contextName) {
|
load: function (name, req, onLoad, config) {
|
||||||
//Make sure the root bundle is loaded, to check if we can support
|
config = config || {};
|
||||||
//loading the requested locale, or if a different one needs
|
|
||||||
//to be chosen.
|
var masterName,
|
||||||
var masterName, context = require.s.contexts[contextName], bundle,
|
match = nlsRegExp.exec(name),
|
||||||
match = nlsRegExp.exec(name), locale = match[4];
|
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,
|
//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
|
//so it does not have to be handled. Locale-specific requests
|
||||||
//(a match[4] value but no match[5])
|
//will have a match[4] value but no match[5]
|
||||||
if (match[5]) {
|
if (match[5]) {
|
||||||
//locale-specific bundle
|
//locale-specific bundle
|
||||||
masterName = match[1] + match[5];
|
prefix = match[1];
|
||||||
bundle = context.nls[masterName];
|
masterName = prefix + suffix;
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
//Top-level bundle. Just call regular load, if not already loaded
|
//Top-level bundle.
|
||||||
if (!context.nlsRootLoaded[name]) {
|
masterName = name;
|
||||||
context.defPlugin[name] = 'i18n';
|
suffix = match[4];
|
||||||
require.load(name, contextName);
|
locale = config.locale || (config.locale =
|
||||||
}
|
typeof navigator === "undefined" ? "root" :
|
||||||
|
(navigator.language ||
|
||||||
|
navigator.userLanguage || "root").toLowerCase());
|
||||||
|
parts = locale.split("-");
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
if (config.isBuild) {
|
||||||
* Called when the dependencies of a module are checked.
|
//Check for existence of all locale possible files and
|
||||||
*/
|
//require them if exist.
|
||||||
checkDeps: function (name, deps, context) {
|
toLoad.push(masterName);
|
||||||
//i18n bundles are always defined as objects for their "dependencies",
|
addIfExists(req, "root", toLoad, prefix, suffix);
|
||||||
//and that object is already processed in the require method, no need to
|
for (i = 0; (part = parts[i]); i++) {
|
||||||
//do work in here.
|
current += (current ? "-" : "") + part;
|
||||||
},
|
addIfExists(req, current, toLoad, prefix, suffix);
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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
|
//Always allow for root, then do the rest of the locale parts.
|
||||||
//loop above so that the default locale bundle has been properly mixed
|
addPart("root", master, needed, toLoad, prefix, suffix);
|
||||||
//together.
|
for (i = 0; (part = parts[i]); i++) {
|
||||||
context.defined[master] = context.defined[modulePrefix + "/" + defLoc + "/" + moduleSuffix];
|
current += (current ? "-" : "") + part;
|
||||||
|
addPart(current, master, needed, toLoad, prefix, suffix);
|
||||||
//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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
//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.
|
* @license RequireJS order 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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
/*jslint nomen: false, plusplus: false */
|
/*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";
|
"use strict";
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
|
@ -14,39 +15,65 @@
|
||||||
//Currently, Gecko and Opera do not load/fire onload for scripts with
|
//Currently, Gecko and Opera do not load/fire onload for scripts with
|
||||||
//type="script/cache" but they execute injected scripts in order
|
//type="script/cache" but they execute injected scripts in order
|
||||||
//unless the 'async' flag is present.
|
//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
|
//If Firefox 2 does not have to be supported, then
|
||||||
//a better check may be:
|
//a better check may be:
|
||||||
//('mozIsLocallyAvailable' in window.navigator)
|
//('mozIsLocallyAvailable' in window.navigator)
|
||||||
("MozAppearance" in document.documentElement.style)),
|
("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
|
//Callback used by the type="script/cache" callback that indicates a script
|
||||||
//has finished downloading.
|
//has finished downloading.
|
||||||
function scriptCacheCallback(evt) {
|
function scriptCacheCallback(evt) {
|
||||||
var node = evt.currentTarget || evt.srcElement, i,
|
var node = evt.currentTarget || evt.srcElement, i,
|
||||||
context, contextName, moduleName, waiting, cached;
|
moduleName, resource;
|
||||||
|
|
||||||
if (evt.type === "load" || readyRegExp.test(node.readyState)) {
|
if (evt.type === "load" || readyRegExp.test(node.readyState)) {
|
||||||
//Pull out the name of the module and the context.
|
//Pull out the name of the module and the context.
|
||||||
contextName = node.getAttribute("data-requirecontext");
|
|
||||||
moduleName = node.getAttribute("data-requiremodule");
|
moduleName = node.getAttribute("data-requiremodule");
|
||||||
context = require.s.contexts[contextName];
|
|
||||||
waiting = context.orderWaiting;
|
|
||||||
cached = context.orderCached;
|
|
||||||
|
|
||||||
//Mark this cache request as loaded
|
//Mark this cache request as loaded
|
||||||
cached[moduleName] = true;
|
cached[moduleName] = true;
|
||||||
|
|
||||||
//Find out how many ordered modules have loaded
|
//Find out how many ordered modules have loaded
|
||||||
for (i = 0; cached[waiting[i]]; i++) {}
|
for (i = 0; (resource = waiting[i]); i++) {
|
||||||
if (i > 0) {
|
if (cached[resource.name]) {
|
||||||
require(waiting.splice(0, i), contextName);
|
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 just loaded some items, remove them from waiting.
|
||||||
if (!waiting.length) {
|
if (i > 0) {
|
||||||
context.orderCached = {};
|
waiting.splice(0, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove this script tag from the DOM
|
//Remove this script tag from the DOM
|
||||||
|
@ -58,34 +85,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
require.plugin({
|
define({
|
||||||
prefix: "order",
|
load: function (name, req, onLoad, config) {
|
||||||
|
var url = req.nameToUrl(name, null);
|
||||||
|
|
||||||
/**
|
//If a build, just load the module as usual.
|
||||||
* This callback is prefix-specific, only gets called for this prefix
|
if (config.isBuild) {
|
||||||
*/
|
loadResource(name, req, onLoad);
|
||||||
require: function (name, deps, callback, context) {
|
return;
|
||||||
//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);
|
|
||||||
|
|
||||||
//Make sure the async attribute is not set for any pathway involving
|
//Make sure the async attribute is not set for any pathway involving
|
||||||
//this script.
|
//this script.
|
||||||
|
@ -93,7 +101,14 @@
|
||||||
if (supportsInOrderExecution) {
|
if (supportsInOrderExecution) {
|
||||||
//Just a normal script tag append, but without async attribute
|
//Just a normal script tag append, but without async attribute
|
||||||
//on the script.
|
//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 {
|
} else {
|
||||||
//Credit to LABjs author Kyle Simpson for finding that scripts
|
//Credit to LABjs author Kyle Simpson for finding that scripts
|
||||||
//with type="script/cache" allow scripts to be downloaded into
|
//with type="script/cache" allow scripts to be downloaded into
|
||||||
|
@ -101,32 +116,24 @@
|
||||||
//so that subsequent addition of a real type="text/javascript"
|
//so that subsequent addition of a real type="text/javascript"
|
||||||
//tag will cause the scripts to be executed immediately in the
|
//tag will cause the scripts to be executed immediately in the
|
||||||
//correct order.
|
//correct order.
|
||||||
context.orderWaiting.push(name);
|
if (req.isDefined(name)) {
|
||||||
context.loaded[name] = false;
|
req([name], function (value) {
|
||||||
require.attach(url, contextName, name, scriptCacheCallback, "script/cache");
|
//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.
|
* @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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
/*global require: false, readFile: false */
|
/*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().
|
CommonJS modules, by overriding require.get().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*globals load: false */
|
/*globals load: false, java: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
require.load = function (moduleName, contextName) {
|
(function () {
|
||||||
var url = require.nameToUrl(moduleName, null, contextName),
|
|
||||||
context = require.s.contexts[contextName];
|
|
||||||
|
|
||||||
//isDone is used by require.ready()
|
var fileUtil = {
|
||||||
require.s.isDone = false;
|
backSlashRegExp: /\\/g,
|
||||||
|
|
||||||
//Indicate a the module is in process of loading.
|
getLineSeparator: function () {
|
||||||
context.loaded[moduleName] = false;
|
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.
|
//Indicate a the module is in process of loading.
|
||||||
require.completeLoad(moduleName, context);
|
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.
|
* @license RequireJS text 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
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
/*jslint regexp: false, nomen: false, plusplus: false */
|
/*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";
|
"use strict";
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
|
var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
|
||||||
xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
|
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) {
|
if (!require.textStrip) {
|
||||||
require.textStrip = function (text) {
|
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
|
//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
|
//this require is used in a non-browser env, so detect for existing method
|
||||||
//before attaching one.
|
//before attaching one.
|
||||||
|
@ -50,7 +63,7 @@
|
||||||
progIds = [progId]; // so faster next time
|
progIds = [progId]; // so faster next time
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!xhr) {
|
if (!xhr) {
|
||||||
|
@ -60,7 +73,7 @@
|
||||||
return xhr;
|
return xhr;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!require.fetchText) {
|
if (!require.fetchText) {
|
||||||
require.fetchText = function (url, callback) {
|
require.fetchText = function (url, callback) {
|
||||||
var xhr = require.getXhr();
|
var xhr = require.getXhr();
|
||||||
|
@ -76,120 +89,43 @@
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
require.plugin({
|
define({
|
||||||
prefix: "text",
|
load: function (name, req, onLoad, config) {
|
||||||
|
//Name has format: some.module.filext!strip
|
||||||
/**
|
//The strip part is optional.
|
||||||
* 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.
|
|
||||||
//if strip is present, then that means only get the string contents
|
//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
|
//inside a body tag in an HTML string. For XML/SVG content it means
|
||||||
//removing the <?xml ...?> declarations so the content can be inserted
|
//removing the <?xml ...?> declarations so the content can be inserted
|
||||||
//into the current doc without problems.
|
//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("."),
|
var strip = false, url, index = name.indexOf("."),
|
||||||
modName = name.substring(0, index), fullKey,
|
modName = name.substring(0, index),
|
||||||
ext = name.substring(index + 1, name.length),
|
ext = name.substring(index + 1, name.length);
|
||||||
context = require.s.contexts[contextName],
|
|
||||||
tWaitAry = context.textWaiting;
|
|
||||||
|
|
||||||
index = ext.indexOf("!");
|
index = ext.indexOf("!");
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
//Pull off the strip arg.
|
//Pull off the strip arg.
|
||||||
strip = ext.substring(index + 1, ext.length);
|
strip = ext.substring(index + 1, ext.length);
|
||||||
|
strip = strip === "strip";
|
||||||
ext = ext.substring(0, index);
|
ext = ext.substring(0, index);
|
||||||
index = strip.indexOf("!");
|
}
|
||||||
if (index !== -1 && strip.substring(0, index) === "strip") {
|
|
||||||
//Pull off the text.
|
//Load the text.
|
||||||
text = strip.substring(index + 1, strip.length);
|
url = req.nameToUrl(modName, "." + ext);
|
||||||
strip = "strip";
|
require.fetchText(url, function (text) {
|
||||||
} else if (strip !== "strip") {
|
text = strip ? require.textStrip(text) : text;
|
||||||
//strip is actually the inlined text.
|
if (config.isBuild && config.inlineText) {
|
||||||
text = strip;
|
buildMap[name] = text;
|
||||||
strip = null;
|
|
||||||
}
|
}
|
||||||
}
|
onLoad(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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
write: function (pluginName, moduleName, write) {
|
||||||
* Called when the dependencies of a module are checked.
|
if (moduleName in buildMap) {
|
||||||
*/
|
var text = require.jsEscape(buildMap[moduleName]);
|
||||||
checkDeps: function (name, deps, context) {
|
write("define('" + pluginName + "!" + moduleName +
|
||||||
//No-op, checkDeps never gets these text items, they are always
|
"', function () { return '" + text + "';});\n");
|
||||||
//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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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 |