1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-22 13:30:55 +01:00

Bring Javelin into Phabricator via git submodule, not copy-and-paste

Summary:
Javelin is currently embedded in Phabricator via copy-and-paste of prebuilt
packages. This is not so great.

Pull it in as a submodule instead and make all the Phabriator resources declare
proper dependency trees. Add Javelin linting.

Test Plan:
I tried to run through pretty much all the JS functionality on the site. This is
still a high-risk change, but I did a pretty thorough test

Differential: inline comments, revealing diffs, list tokenizers, comment
preview, editing/deleting comments, add review action.
Maniphest: list tokenizer, comment actions
Herald: rule editing, tokenizers, add/remove rows

Reviewed By: tomo
Reviewers: aran, tomo, mroch, jungejason, tuomaspelkonen
CC: aran, tomo, epriestley
Differential Revision: 223
This commit is contained in:
epriestley 2011-05-03 15:11:55 -07:00
parent 846d625ed0
commit 2a39fd09eb
46 changed files with 880 additions and 4716 deletions

View file

@ -1,7 +1,7 @@
{
"project_id" : "phabricator",
"conduit_uri" : "https://secure.phabricator.com/api/",
"lint_engine" : "PhutilLintEngine",
"lint_engine" : "PhabricatorLintEngine",
"unit_engine" : "PhutilUnitTestEngine",
"copyright_holder" : "Facebook, Inc.",
"remote_hooks_installed" : true,

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "externals/javelin"]
path = externals/javelin
url = git://github.com/epriestley/javelin.git

1
externals/javelin vendored Submodule

@ -0,0 +1 @@
Subproject commit 099162f62bbb154c2d906cbe3c7ab3e58e89be7e

View file

@ -2,6 +2,32 @@
<?php
$package_spec = array(
'javelin.pkg.js' => array(
'javelin-util',
'javelin-install',
'javelin-event',
'javelin-stratcom',
'javelin-behavior',
'javelin-request',
'javelin-vector',
'javelin-dom',
'javelin-json',
'javelin-uri',
),
'typeahead.pkg.js' => array(
'javelin-typeahead',
'javelin-typeahead-normalizer',
'javelin-typeahead-source',
'javelin-typeahead-preloaded-source',
'javelin-typeahead-ondemand-source',
'javelin-tokenizer',
'javelin-behavior-aphront-basic-tokenizer',
),
'workflow.pkg.js' => array(
'javelin-mask',
'javelin-workflow',
'javelin-behavior-workflow',
),
'core.pkg.css' => array(
'phabricator-core-css',
'phabricator-core-buttons-css',
@ -14,6 +40,7 @@ $package_spec = array(
'aphront-crumbs-view-css',
'aphront-tokenizer-control-css',
'aphront-typeahead-control-css',
'aphront-list-filter-view-css',
'phabricator-directory-css',
@ -63,6 +90,7 @@ $files = id(new FileFinder($root))
->withType('f')
->withSuffix('js')
->withSuffix('css')
->withFollowSymlinks(true)
->setGenerateChecksums(true)
->find();
@ -101,9 +129,10 @@ foreach ($file_map as $path => $info) {
$provides = array_filter($provides);
$requires = array_filter($requires);
if (count($provides) !== 1) {
if (count($provides) > 1) {
// NOTE: Documentation-only JS is permitted to @provide no targets.
throw new Exception(
"File {$path} must @provide exactly one Celerity target.");
"File {$path} must @provide at most one Celerity target.");
}
$provides = reset($provides);

View file

@ -235,14 +235,19 @@ celerity_register_resource_map(array(
),
'herald-rule-editor' =>
array(
'uri' => '/res/ec8e2110/rsrc/js/application/herald/HeraldRuleEditor.js',
'uri' => '/res/f3122b0a/rsrc/js/application/herald/HeraldRuleEditor.js',
'type' => 'js',
'requires' =>
array(
0 => 'multirow-row-manager',
1 => 'javelin-lib-dev',
2 => 'javelin-typeahead-dev',
3 => 'path-typeahead',
1 => 'javelin-install',
2 => 'javelin-typeahead',
3 => 'javelin-util',
4 => 'javelin-dom',
5 => 'javelin-tokenizer',
6 => 'javelin-typeahead-preloaded-source',
7 => 'javelin-stratcom',
8 => 'javelin-json',
),
'disk' => '/rsrc/js/application/herald/HeraldRuleEditor.js',
),
@ -255,248 +260,463 @@ celerity_register_resource_map(array(
),
'disk' => '/rsrc/css/application/herald/herald-test.css',
),
'javelin-behavior-aphront-basic-tokenizer' =>
'javelin-behavior' =>
array(
'uri' => '/res/8317d761/rsrc/js/application/core/behavior-tokenizer.js',
'uri' => '/res/dc576a49/rsrc/js/javelin/lib/behavior.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
),
'disk' => '/rsrc/js/javelin/lib/behavior.js',
),
'javelin-behavior-aphront-basic-tokenizer' =>
array(
'uri' => '/res/d48d2732/rsrc/js/application/core/behavior-tokenizer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-typeahead',
2 => 'javelin-tokenizer',
3 => 'javelin-typeahead-preloaded-source',
4 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-tokenizer.js',
),
'javelin-behavior-dark-console' =>
0 =>
array(
'uri' => '/res/020b0265/rsrc/js/application/core/behavior-dark-console.js',
'uri' => '/res/e3d992aa/rsrc/js/javelin/docs/Base.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/docs/Base.js',
),
'javelin-behavior-dark-console' =>
array(
'uri' => '/res/447bd50a/rsrc/js/application/core/behavior-dark-console.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-util',
3 => 'javelin-dom',
4 => 'javelin-request',
),
'disk' => '/rsrc/js/application/core/behavior-dark-console.js',
),
'javelin-behavior-differential-add-reviewers' =>
array(
'uri' => '/res/330154e4/rsrc/js/application/differential/behavior-add-reviewers.js',
'uri' => '/res/fa2f29c4/rsrc/js/application/differential/behavior-add-reviewers.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-tokenizer',
3 => 'javelin-typeahead',
4 => 'javelin-typeahead-preloaded-source',
),
'disk' => '/rsrc/js/application/differential/behavior-add-reviewers.js',
),
'javelin-behavior-differential-diff-radios' =>
array(
'uri' => '/res/fdeb3823/rsrc/js/application/differential/behavior-diff-radios.js',
'uri' => '/res/d3365dba/rsrc/js/application/differential/behavior-diff-radios.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-diff-radios.js',
),
'javelin-behavior-differential-edit-inline-comments' =>
array(
'uri' => '/res/6a6f38e6/rsrc/js/application/differential/behavior-edit-inline-comments.js',
'uri' => '/res/f18ee6ae/rsrc/js/application/differential/behavior-edit-inline-comments.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-workflow',
4 => 'javelin-vector',
),
'disk' => '/rsrc/js/application/differential/behavior-edit-inline-comments.js',
),
'javelin-behavior-differential-feedback-preview' =>
array(
'uri' => '/res/8695d8b8/rsrc/js/application/differential/behavior-comment-preview.js',
'uri' => '/res/139c85b8/rsrc/js/application/differential/behavior-comment-preview.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-request',
4 => 'javelin-util',
),
'disk' => '/rsrc/js/application/differential/behavior-comment-preview.js',
),
'javelin-behavior-differential-populate' =>
array(
'uri' => '/res/a13dcd7e/rsrc/js/application/differential/behavior-populate.js',
'uri' => '/res/d4d4fd9d/rsrc/js/application/differential/behavior-populate.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-request',
2 => 'javelin-util',
3 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-populate.js',
),
'javelin-behavior-differential-show-all-comments' =>
array(
'uri' => '/res/2a3592b8/rsrc/js/application/differential/behavior-show-all-comments.js',
'uri' => '/res/4d34a1e7/rsrc/js/application/differential/behavior-show-all-comments.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/differential/behavior-show-all-comments.js',
),
'javelin-behavior-differential-show-more' =>
array(
'uri' => '/res/ea998002/rsrc/js/application/differential/behavior-show-more.js',
'uri' => '/res/6af8c5bb/rsrc/js/application/differential/behavior-show-more.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-request',
3 => 'javelin-util',
4 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/differential/behavior-show-more.js',
),
'javelin-behavior-diffusion-jump-to' =>
array(
'uri' => '/res/4f3f6cdc/rsrc/js/application/diffusion/behavior-jump-to.js',
'uri' => '/res/2a8ca30b/rsrc/js/application/diffusion/behavior-jump-to.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-util',
2 => 'javelin-vector',
3 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/diffusion/behavior-jump-to.js',
),
'javelin-behavior-diffusion-pull-lastmodified' =>
array(
'uri' => '/res/6a5e7374/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
'uri' => '/res/f3e3f3a6/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-request',
),
'disk' => '/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
),
'javelin-behavior-error-log' =>
array(
'uri' => '/res/c57a323f/rsrc/js/application/core/behavior-error-log.js',
'uri' => '/res/ad4e82d4/rsrc/js/application/core/behavior-error-log.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-dom',
),
'disk' => '/rsrc/js/application/core/behavior-error-log.js',
),
'javelin-behavior-herald-rule-editor' =>
array(
'uri' => '/res/48108130/rsrc/js/application/herald/herald-rule-editor.js',
'uri' => '/res/f18bcd5e/rsrc/js/application/herald/herald-rule-editor.js',
'type' => 'js',
'requires' =>
array(
0 => 'herald-rule-editor',
1 => 'javelin-lib-dev',
1 => 'javelin-behavior',
),
'disk' => '/rsrc/js/application/herald/herald-rule-editor.js',
),
'javelin-behavior-maniphest-transaction-controls' =>
array(
'uri' => '/res/fc6a8722/rsrc/js/application/maniphest/behavior-transaction-controls.js',
'uri' => '/res/f2eae88a/rsrc/js/application/maniphest/behavior-transaction-controls.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-tokenizer',
3 => 'javelin-typeahead',
4 => 'javelin-typeahead-preloaded-source',
),
'disk' => '/rsrc/js/application/maniphest/behavior-transaction-controls.js',
),
'javelin-behavior-owners-path-editor' =>
array(
'uri' => '/res/7568aa22/rsrc/js/application/owners/owners-path-editor.js',
'uri' => '/res/b379a0d4/rsrc/js/application/owners/owners-path-editor.js',
'type' => 'js',
'requires' =>
array(
0 => 'owners-path-editor',
1 => 'javelin-lib-dev',
1 => 'javelin-behavior',
),
'disk' => '/rsrc/js/application/owners/owners-path-editor.js',
),
'javelin-behavior-phabricator-object-selector' =>
array(
'uri' => '/res/85d0769b/rsrc/js/application/core/behavior-object-selector.js',
'uri' => '/res/e899a55e/rsrc/js/application/core/behavior-object-selector.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-dom',
2 => 'javelin-request',
3 => 'javelin-util',
4 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/application/core/behavior-object-selector.js',
),
'javelin-behavior-workflow' =>
array(
'uri' => '/res/15446e7e/rsrc/js/application/core/behavior-workflow.js',
'uri' => '/res/b5bc59cb/rsrc/js/application/core/behavior-workflow.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-behavior',
1 => 'javelin-stratcom',
2 => 'javelin-workflow',
),
'disk' => '/rsrc/js/application/core/behavior-workflow.js',
),
'javelin-init-prod' =>
'javelin-dom' =>
array(
'uri' => '/res/1267c868/rsrc/js/javelin/init.min.js',
'uri' => '/res/21c1392d/rsrc/js/javelin/lib/DOM.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-vector',
3 => 'javelin-stratcom',
),
'disk' => '/rsrc/js/javelin/init.min.js',
'disk' => '/rsrc/js/javelin/lib/DOM.js',
),
'javelin-lib-dev' =>
'javelin-event' =>
array(
'uri' => '/res/a0e7a5e9/rsrc/js/javelin/javelin.dev.js',
'uri' => '/res/807b95e6/rsrc/js/javelin/core/Event.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/javelin.dev.js',
'disk' => '/rsrc/js/javelin/core/Event.js',
),
'javelin-lib-prod' =>
'javelin-install' =>
array(
'uri' => '/res/2f2b3b2e/rsrc/js/javelin/javelin.min.js',
'uri' => '/res/c11fe5b3/rsrc/js/javelin/core/install.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/javelin.min.js',
'disk' => '/rsrc/js/javelin/core/install.js',
),
'javelin-json' =>
array(
'uri' => '/res/62c8cc8d/rsrc/js/javelin/lib/JSON.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/lib/JSON.js',
),
'javelin-magical-init' =>
array(
'uri' => '/res/76614f84/rsrc/js/javelin/init.dev.js',
'uri' => '/res/6d53e259/rsrc/js/javelin/core/init.js',
'type' => 'js',
'requires' =>
array(
),
'disk' => '/rsrc/js/javelin/init.dev.js',
'disk' => '/rsrc/js/javelin/core/init.js',
),
'javelin-typeahead-dev' =>
'javelin-mask' =>
array(
'uri' => '/res/6de6ae59/rsrc/js/javelin/typeahead.dev.js',
'uri' => '/res/ba2f665a/rsrc/js/javelin/lib/Mask.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-vector',
2 => 'javelin-dom',
),
'disk' => '/rsrc/js/javelin/typeahead.dev.js',
'disk' => '/rsrc/js/javelin/lib/Mask.js',
),
'javelin-typeahead-prod' =>
'javelin-request' =>
array(
'uri' => '/res/69d5fad1/rsrc/js/javelin/typeahead.min.js',
'uri' => '/res/3947083d/rsrc/js/javelin/lib/Request.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-stratcom',
2 => 'javelin-util',
3 => 'javelin-behavior',
),
'disk' => '/rsrc/js/javelin/typeahead.min.js',
'disk' => '/rsrc/js/javelin/lib/Request.js',
),
'javelin-workflow-dev' =>
'javelin-stratcom' =>
array(
'uri' => '/res/c6b17f93/rsrc/js/javelin/workflow.dev.js',
'uri' => '/res/3421b115/rsrc/js/javelin/core/Stratcom.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-event',
2 => 'javelin-util',
3 => 'javelin-magical-init',
),
'disk' => '/rsrc/js/javelin/workflow.dev.js',
'disk' => '/rsrc/js/javelin/core/Stratcom.js',
),
'javelin-workflow-prod' =>
'javelin-tokenizer' =>
array(
'uri' => '/res/b758e0a0/rsrc/js/javelin/workflow.min.js',
'uri' => '/res/74fe92c6/rsrc/js/javelin/lib/control/tokenizer/Tokenizer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-typeahead',
1 => 'javelin-dom',
2 => 'javelin-util',
3 => 'javelin-stratcom',
4 => 'javelin-vector',
5 => 'javelin-install',
6 => 'javelin-typeahead-preloaded-source',
),
'disk' => '/rsrc/js/javelin/workflow.min.js',
'disk' => '/rsrc/js/javelin/lib/control/tokenizer/Tokenizer.js',
),
'javelin-typeahead' =>
array(
'uri' => '/res/5a701345/rsrc/js/javelin/lib/control/typeahead/Typeahead.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-dom',
2 => 'javelin-vector',
3 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/Typeahead.js',
),
'javelin-typeahead-normalizer' =>
array(
'uri' => '/res/8d49e2de/rsrc/js/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/normalizer/TypeaheadNormalizer.js',
),
'javelin-typeahead-ondemand-source' =>
array(
'uri' => '/res/00b46be8/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-request',
4 => 'javelin-typeahead-source',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadOnDemandSource.js',
),
'javelin-typeahead-preloaded-source' =>
array(
'uri' => '/res/aefaf410/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-stratcom',
3 => 'javelin-request',
4 => 'javelin-typeahead-source',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js',
),
'javelin-typeahead-source' =>
array(
'uri' => '/res/b1184e7d/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadSource.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
2 => 'javelin-dom',
3 => 'javelin-typeahead-normalizer',
),
'disk' => '/rsrc/js/javelin/lib/control/typeahead/source/TypeaheadSource.js',
),
'javelin-uri' =>
array(
'uri' => '/res/03448af9/rsrc/js/javelin/lib/URI.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-util',
),
'disk' => '/rsrc/js/javelin/lib/URI.js',
),
'javelin-util' =>
array(
'uri' => '/res/031851eb/rsrc/js/javelin/core/util.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-magical-init',
),
'disk' => '/rsrc/js/javelin/core/util.js',
),
'javelin-vector' =>
array(
'uri' => '/res/184e9d71/rsrc/js/javelin/lib/Vector.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-install',
1 => 'javelin-event',
),
'disk' => '/rsrc/js/javelin/lib/Vector.js',
),
'javelin-workflow' =>
array(
'uri' => '/res/24389bc8/rsrc/js/javelin/lib/Workflow.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-stratcom',
1 => 'javelin-request',
2 => 'javelin-dom',
3 => 'javelin-vector',
4 => 'javelin-install',
5 => 'javelin-util',
6 => 'javelin-mask',
7 => 'javelin-uri',
),
'disk' => '/rsrc/js/javelin/lib/Workflow.js',
),
'mainphest-task-detail-css' =>
array(
@ -527,24 +747,28 @@ celerity_register_resource_map(array(
),
'multirow-row-manager' =>
array(
'uri' => '/res/330d076b/rsrc/js/application/core/MultirowRowManager.js',
'uri' => '/res/cae26c67/rsrc/js/application/core/MultirowRowManager.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
0 => 'javelin-install',
1 => 'javelin-stratcom',
2 => 'javelin-dom',
3 => 'javelin-util',
),
'disk' => '/rsrc/js/application/core/MultirowRowManager.js',
),
'owners-path-editor' =>
array(
'uri' => '/res/b01c1ca9/rsrc/js/application/owners/OwnersPathEditor.js',
'uri' => '/res/003f3d3f/rsrc/js/application/owners/OwnersPathEditor.js',
'type' => 'js',
'requires' =>
array(
0 => 'multirow-row-manager',
1 => 'javelin-lib-dev',
2 => 'javelin-typeahead-dev',
3 => 'path-typeahead',
1 => 'javelin-install',
2 => 'path-typeahead',
3 => 'javelin-dom',
4 => 'javelin-util',
),
'disk' => '/rsrc/js/application/owners/OwnersPathEditor.js',
),
@ -559,12 +783,16 @@ celerity_register_resource_map(array(
),
'path-typeahead' =>
array(
'uri' => '/res/42fb76c3/rsrc/js/application/herald/PathTypeahead.js',
'uri' => '/res/594d2576/rsrc/js/application/herald/PathTypeahead.js',
'type' => 'js',
'requires' =>
array(
0 => 'javelin-lib-dev',
1 => 'javelin-typeahead-dev',
0 => 'javelin-install',
1 => 'javelin-typeahead',
2 => 'javelin-dom',
3 => 'javelin-request',
4 => 'javelin-typeahead-ondemand-source',
5 => 'javelin-util',
),
'disk' => '/rsrc/js/application/herald/PathTypeahead.js',
),
@ -653,30 +881,7 @@ celerity_register_resource_map(array(
), array (
'packages' =>
array (
'4270730a' =>
array (
'name' => 'core.pkg.css',
'symbols' =>
array (
0 => 'phabricator-core-css',
1 => 'phabricator-core-buttons-css',
2 => 'phabricator-standard-page-view',
3 => 'aphront-dialog-view-css',
4 => 'aphront-form-view-css',
5 => 'aphront-panel-view-css',
6 => 'aphront-side-nav-view-css',
7 => 'aphront-table-view-css',
8 => 'aphront-crumbs-view-css',
9 => 'aphront-tokenizer-control-css',
10 => 'aphront-typeahead-control-css',
11 => 'phabricator-directory-css',
12 => 'phabricator-remarkup-css',
13 => 'syntax-highlighting-css',
),
'uri' => '/res/pkg/4270730a/core.pkg.css',
'type' => 'css',
),
'6c786373' =>
'3b698834' =>
array (
'name' => 'differential.pkg.js',
'symbols' =>
@ -687,7 +892,19 @@ celerity_register_resource_map(array(
3 => 'javelin-behavior-differential-show-more',
4 => 'javelin-behavior-differential-diff-radios',
),
'uri' => '/res/pkg/6c786373/differential.pkg.js',
'uri' => '/res/pkg/3b698834/differential.pkg.js',
'type' => 'js',
),
'71a78877' =>
array (
'name' => 'workflow.pkg.js',
'symbols' =>
array (
0 => 'javelin-mask',
1 => 'javelin-workflow',
2 => 'javelin-behavior-workflow',
),
'uri' => '/res/pkg/71a78877/workflow.pkg.js',
'type' => 'js',
),
'8e4ef51b' =>
@ -707,6 +924,46 @@ celerity_register_resource_map(array(
'uri' => '/res/pkg/8e4ef51b/differential.pkg.css',
'type' => 'css',
),
'a44a7841' =>
array (
'name' => 'typeahead.pkg.js',
'symbols' =>
array (
0 => 'javelin-typeahead',
1 => 'javelin-typeahead-normalizer',
2 => 'javelin-typeahead-source',
3 => 'javelin-typeahead-preloaded-source',
4 => 'javelin-typeahead-ondemand-source',
5 => 'javelin-tokenizer',
6 => 'javelin-behavior-aphront-basic-tokenizer',
),
'uri' => '/res/pkg/a44a7841/typeahead.pkg.js',
'type' => 'js',
),
'c4276ad7' =>
array (
'name' => 'core.pkg.css',
'symbols' =>
array (
0 => 'phabricator-core-css',
1 => 'phabricator-core-buttons-css',
2 => 'phabricator-standard-page-view',
3 => 'aphront-dialog-view-css',
4 => 'aphront-form-view-css',
5 => 'aphront-panel-view-css',
6 => 'aphront-side-nav-view-css',
7 => 'aphront-table-view-css',
8 => 'aphront-crumbs-view-css',
9 => 'aphront-tokenizer-control-css',
10 => 'aphront-typeahead-control-css',
11 => 'aphront-list-filter-view-css',
12 => 'phabricator-directory-css',
13 => 'phabricator-remarkup-css',
14 => 'syntax-highlighting-css',
),
'uri' => '/res/pkg/c4276ad7/core.pkg.css',
'type' => 'css',
),
'eadf6ec3' =>
array (
'name' => 'diffusion.pkg.css',
@ -717,17 +974,37 @@ celerity_register_resource_map(array(
'uri' => '/res/pkg/eadf6ec3/diffusion.pkg.css',
'type' => 'css',
),
'fc6ed8bc' =>
array (
'name' => 'javelin.pkg.js',
'symbols' =>
array (
0 => 'javelin-util',
1 => 'javelin-install',
2 => 'javelin-event',
3 => 'javelin-stratcom',
4 => 'javelin-behavior',
5 => 'javelin-request',
6 => 'javelin-vector',
7 => 'javelin-dom',
8 => 'javelin-json',
9 => 'javelin-uri',
),
'uri' => '/res/pkg/fc6ed8bc/javelin.pkg.js',
'type' => 'js',
),
),
'reverse' =>
array (
'aphront-crumbs-view-css' => '4270730a',
'aphront-dialog-view-css' => '4270730a',
'aphront-form-view-css' => '4270730a',
'aphront-panel-view-css' => '4270730a',
'aphront-side-nav-view-css' => '4270730a',
'aphront-table-view-css' => '4270730a',
'aphront-tokenizer-control-css' => '4270730a',
'aphront-typeahead-control-css' => '4270730a',
'aphront-crumbs-view-css' => 'c4276ad7',
'aphront-dialog-view-css' => 'c4276ad7',
'aphront-form-view-css' => 'c4276ad7',
'aphront-list-filter-view-css' => 'c4276ad7',
'aphront-panel-view-css' => 'c4276ad7',
'aphront-side-nav-view-css' => 'c4276ad7',
'aphront-table-view-css' => 'c4276ad7',
'aphront-tokenizer-control-css' => 'c4276ad7',
'aphront-typeahead-control-css' => 'c4276ad7',
'differential-changeset-view-css' => '8e4ef51b',
'differential-core-view-css' => '8e4ef51b',
'differential-revision-add-comment-css' => '8e4ef51b',
@ -737,16 +1014,36 @@ celerity_register_resource_map(array(
'differential-revision-history-css' => '8e4ef51b',
'differential-table-of-contents-css' => '8e4ef51b',
'diffusion-commit-view-css' => 'eadf6ec3',
'javelin-behavior-differential-diff-radios' => '6c786373',
'javelin-behavior-differential-edit-inline-comments' => '6c786373',
'javelin-behavior-differential-feedback-preview' => '6c786373',
'javelin-behavior-differential-populate' => '6c786373',
'javelin-behavior-differential-show-more' => '6c786373',
'phabricator-core-buttons-css' => '4270730a',
'phabricator-core-css' => '4270730a',
'phabricator-directory-css' => '4270730a',
'phabricator-remarkup-css' => '4270730a',
'phabricator-standard-page-view' => '4270730a',
'syntax-highlighting-css' => '4270730a',
'javelin-behavior' => 'fc6ed8bc',
'javelin-behavior-aphront-basic-tokenizer' => 'a44a7841',
'javelin-behavior-differential-diff-radios' => '3b698834',
'javelin-behavior-differential-edit-inline-comments' => '3b698834',
'javelin-behavior-differential-feedback-preview' => '3b698834',
'javelin-behavior-differential-populate' => '3b698834',
'javelin-behavior-differential-show-more' => '3b698834',
'javelin-behavior-workflow' => '71a78877',
'javelin-dom' => 'fc6ed8bc',
'javelin-event' => 'fc6ed8bc',
'javelin-install' => 'fc6ed8bc',
'javelin-json' => 'fc6ed8bc',
'javelin-mask' => '71a78877',
'javelin-request' => 'fc6ed8bc',
'javelin-stratcom' => 'fc6ed8bc',
'javelin-tokenizer' => 'a44a7841',
'javelin-typeahead' => 'a44a7841',
'javelin-typeahead-normalizer' => 'a44a7841',
'javelin-typeahead-ondemand-source' => 'a44a7841',
'javelin-typeahead-preloaded-source' => 'a44a7841',
'javelin-typeahead-source' => 'a44a7841',
'javelin-uri' => 'fc6ed8bc',
'javelin-util' => 'fc6ed8bc',
'javelin-vector' => 'fc6ed8bc',
'javelin-workflow' => '71a78877',
'phabricator-core-buttons-css' => 'c4276ad7',
'phabricator-core-css' => 'c4276ad7',
'phabricator-directory-css' => 'c4276ad7',
'phabricator-remarkup-css' => 'c4276ad7',
'phabricator-standard-page-view' => 'c4276ad7',
'syntax-highlighting-css' => 'c4276ad7',
),
));

View file

@ -318,6 +318,8 @@ phutil_register_library_map(array(
'PhabricatorFileViewController' => 'applications/files/controller/view',
'PhabricatorGoodForNothingWorker' => 'infrastructure/daemon/workers/worker/goodfornothing',
'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/selector',
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/javelin',
'PhabricatorLintEngine' => 'infrastructure/lint/engine',
'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
'PhabricatorLoginController' => 'applications/auth/controller/login',
'PhabricatorLogoutController' => 'applications/auth/controller/logout',
@ -731,6 +733,8 @@ phutil_register_library_map(array(
'PhabricatorFileUploadController' => 'PhabricatorFileController',
'PhabricatorFileViewController' => 'PhabricatorFileController',
'PhabricatorGoodForNothingWorker' => 'PhabricatorWorker',
'PhabricatorJavelinLinter' => 'ArcanistLinter',
'PhabricatorLintEngine' => 'PhutilLintEngine',
'PhabricatorLiskDAO' => 'LiskDAO',
'PhabricatorLoginController' => 'PhabricatorAuthController',
'PhabricatorLogoutController' => 'PhabricatorAuthController',

View file

@ -21,6 +21,7 @@ final class CelerityResourceMap {
private static $instance;
private $resourceMap;
private $packageMap;
private $reverseMap;
public static function getInstance() {
if (empty(self::$instance)) {
@ -107,6 +108,21 @@ final class CelerityResourceMap {
return $paths;
}
public function lookupSymbolInformation($symbol) {
return idx($this->resourceMap, $symbol);
}
public function lookupFileInformation($path) {
if (empty($this->reverseMap)) {
$this->reverseMap = array();
foreach ($this->resourceMap as $symbol => $data) {
$data['provides'] = $symbol;
$this->reverseMap[$data['disk']] = $data;
}
}
return idx($this->reverseMap, $path);
}
}
function celerity_register_resource_map(array $map, array $package_map) {

View file

@ -25,6 +25,7 @@ final class CelerityStaticResourceResponse {
private $metadata = array();
private $metadataBlock = 0;
private $behaviors = array();
private $hasRendered = array();
public function __construct() {
if (isset($_REQUEST['__metablock__'])) {
@ -64,14 +65,36 @@ final class CelerityStaticResourceResponse {
return $this;
}
public function renderSingleResource($symbol) {
$map = CelerityResourceMap::getInstance();
$resolved = $map->resolveResources(array($symbol));
$packaged = $map->packageResources($resolved);
return $this->renderPackagedResources($packaged);
}
public function renderResourcesOfType($type) {
$this->resolveResources();
$output = array();
$resources = array();
foreach ($this->packaged as $resource) {
if ($resource['type'] == $type) {
$output[] = $this->renderResource($resource);
$resources[] = $resource;
}
}
return $this->renderPackagedResources($resources);
}
private function renderPackagedResources(array $resources) {
$output = array();
foreach ($resources as $resource) {
if (isset($this->hasRendered[$resource['uri']])) {
continue;
}
$this->hasRendered[$resource['uri']] = true;
$output[] = $this->renderResource($resource);
}
return implode("\n", $output);
}

View file

@ -0,0 +1,45 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class PhabricatorLintEngine extends PhutilLintEngine {
public function buildLinters() {
$linters = parent::buildLinters();
$paths = $this->getPaths();
foreach ($paths as $key => $path) {
if (!$this->pathExists($path)) {
unset($paths[$key]);
}
}
$javelin_linter = new PhabricatorJavelinLinter();
$linters[] = $javelin_linter;
foreach ($paths as $path) {
if (preg_match('/\.js$/', $path)) {
$javelin_linter->addPath($path);
$javelin_linter->addData($path, $this->loadData($path));
}
}
return $linters;
}
}

View file

@ -0,0 +1,14 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('arcanist', 'lint/engine/phutil');
phutil_require_module('phabricator', 'infrastructure/lint/linter/javelin');
phutil_require_source('PhabricatorLintEngine.php');

View file

@ -0,0 +1,207 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class PhabricatorJavelinLinter extends ArcanistLinter {
private $symbols = array();
const LINT_PRIVATE_ACCESS = 1;
const LINT_MISSING_DEPENDENCY = 2;
const LINT_UNNECESSARY_DEPENDENCY = 3;
const LINT_UNKNOWN_DEPENDENCY = 4;
public function willLintPaths(array $paths) {
$futures = array();
foreach ($paths as $path) {
$future = $this->newSymbolsFuture($path);
$futures[$path] = $future;
}
foreach (Futures($futures)->limit(8) as $path => $future) {
$this->symbols[$path] = $future->resolvex();
}
}
public function getLinterName() {
return 'JAVELIN';
}
public function getLintSeverityMap() {
return array();
}
public function getLintNameMap() {
return array(
self::LINT_PRIVATE_ACCESS => 'Private Method/Member Access',
self::LINT_MISSING_DEPENDENCY => 'Missing Javelin Dependency',
self::LINT_UNNECESSARY_DEPENDENCY => 'Unnecessary Javelin Dependency',
self::LINT_UNKNOWN_DEPENDENCY => 'Unknown Javelin Dependency',
);
}
public function lintPath($path) {
list($uses, $installs) = $this->getUsedAndInstalledSymbolsForPath($path);
foreach ($uses as $symbol => $line) {
$parts = explode('.', $symbol);
foreach ($parts as $part) {
if ($part[0] == '_' && $part[1] != '_') {
$base = implode('.', array_slice($parts, 0, 2));
if (!array_key_exists($base, $installs)) {
$this->raiseLintAtLine(
$line,
0,
self::LINT_PRIVATE_ACCESS,
"This file accesses private symbol '{$symbol}' across file ".
"boundaries. You may only access private members and methods ".
"from the file where they are defined.");
}
break;
}
}
}
if ($this->getEngine()->getCommitHookMode()) {
// Don't do the dependency checks in commit-hook mode because we won't
// have an available working copy.
return;
}
$external_classes = array();
foreach ($uses as $symbol => $line) {
$parts = explode('.', $symbol);
$class = implode('.', array_slice($parts, 0, 2));
if (!array_key_exists($class, $external_classes) &&
!array_key_exists($class, $installs)) {
$external_classes[$class] = $line;
}
}
$celerity = CelerityResourceMap::getInstance();
$info = $celerity->lookupFileInformation(substr($path, strlen('webroot')));
$need = $external_classes;
$requires = $info['requires'];
foreach ($requires as $key => $name) {
$symbol_info = $celerity->lookupSymbolInformation($name);
if (!$symbol_info) {
$this->raiseLintAtLine(
0,
0,
self::LINT_UNKNOWN_DEPENDENCY,
"This file @requires component '{$name}', but it does not ".
"exist. You may need to rebuild the Celerity map.");
unset($requires[$key]);
continue;
}
$symbol_path = 'webroot'.$symbol_info['disk'];
list($ignored, $req_install) = $this->getUsedAndInstalledSymbolsForPath(
$symbol_path);
if (array_intersect_key($req_install, $external_classes)) {
$need = array_diff_key($need, $req_install);
unset($requires[$key]);
}
}
foreach ($need as $class => $line) {
$this->raiseLintAtLine(
$line,
0,
self::LINT_MISSING_DEPENDENCY,
"This file uses '{$class}' but does not @requires the component ".
"which installs it. You may need to rebuild the Celerity map.");
}
foreach ($requires as $component) {
$this->raiseLintAtLine(
$line,
0,
self::LINT_UNNECESSARY_DEPENDENCY,
"This file @requires component '{$component}' but does not use ".
"anything it provides.");
}
}
private function loadSymbols($path) {
if (empty($this->symbols[$path])) {
$this->symbols[$path] = $this->newSymbolsFuture($path)->resolvex();
}
return $this->symbols[$path];
}
private function newSymbolsFuture($path) {
$root = dirname(phutil_get_library_root('phabricator'));
$support = $root.'/externals/javelin/support';
$javelinsymbols = $support.'/javelinsymbols/javelinsymbols';
$future = new ExecFuture($javelinsymbols.' # '.escapeshellarg($path));
$future->write($this->getData($path));
return $future;
}
private function getUsedAndInstalledSymbolsForPath($path) {
list($symbols) = $this->loadSymbols($path);
$symbols = explode("\n", trim($symbols));
$uses = array();
$installs = array();
foreach ($symbols as $line) {
$matches = null;
if (!preg_match('/^([?+])([^:]*):(\d+)$/', $line, $matches)) {
throw new Exception(
"Received malformed output from `javelinsymbols`.");
}
$type = $matches[1];
$symbol = $matches[2];
$line = $matches[3];
switch ($type) {
case '?':
$uses[$symbol] = $line;
break;
case '+':
$installs['JX.'.$symbol] = $line;
break;
}
}
$contents = $this->getData($path);
$matches = null;
$count = preg_match_all(
'/@javelin-installs\W+(\S+)/',
$contents,
$matches,
PREG_PATTERN_ORDER);
if ($count) {
foreach ($matches[1] as $symbol) {
$installs[$symbol] = 0;
}
}
return array($uses, $installs);
}
}

View file

@ -0,0 +1,18 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('arcanist', 'lint/linter/base');
phutil_require_module('phabricator', 'infrastructure/celerity/map');
phutil_require_module('phutil', 'future');
phutil_require_module('phutil', 'future/exec');
phutil_require_module('phutil', 'moduleutils');
phutil_require_source('PhabricatorJavelinLinter.php');

View file

@ -63,7 +63,7 @@ class AphrontTokenizerTemplateView extends AphrontView {
'mustcapture' => true,
'name' => $name,
'class' => 'jx-tokenizer-input',
'sigil' => 'tokenizer',
'sigil' => 'tokenizer-input',
'style' => 'width: 0px;',
'disabled' => 'disabled',
'type' => 'text',

View file

@ -42,23 +42,9 @@ class AphrontFormTokenizerControl extends AphrontFormControl {
}
protected function renderInput() {
require_celerity_resource('javelin-typeahead-dev');
$name = $this->getName();
$values = nonempty($this->getValue(), array());
$input = javelin_render_tag(
'input',
array(
'mustcapture' => true,
'name' => $name,
'class' => 'jx-tokenizer-input',
'sigil' => 'tokenizer',
'style' => 'width: 0px;',
'disabled' => 'disabled',
'type' => 'text',
));
if ($this->getID()) {
$id = $this->getID();
} else {

View file

@ -8,7 +8,6 @@
phutil_require_module('phabricator', 'infrastructure/celerity/api');
phutil_require_module('phabricator', 'infrastructure/javelin/api');
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
phutil_require_module('phabricator', 'view/control/tokenizer');
phutil_require_module('phabricator', 'view/form/control/base');

View file

@ -89,9 +89,6 @@ class PhabricatorStandardPageView extends AphrontPageView {
require_celerity_resource('phabricator-core-buttons-css');
require_celerity_resource('phabricator-standard-page-view');
require_celerity_resource('javelin-lib-dev');
require_celerity_resource('javelin-workflow-dev');
Javelin::initBehavior('workflow', array());
if ($console) {
@ -118,8 +115,7 @@ class PhabricatorStandardPageView extends AphrontPageView {
'window.__DEV__=1;'.
'</script>'.
$response->renderResourcesOfType('css').
'<script type="text/javascript" src="/rsrc/js/javelin/init.dev.js">'.
'</script>';
$response->renderSingleResource('javelin-magical-init');
$request = $this->getRequest();
if ($request) {

View file

@ -1,5 +1,8 @@
/**
* @requires javelin-lib-dev
* @requires javelin-install
* javelin-stratcom
* javelin-dom
* javelin-util
* @provides multirow-row-manager
* @javelin
*/

View file

@ -1,5 +1,10 @@
/**
* @provides javelin-behavior-dark-console
* @requires javelin-behavior
* javelin-stratcom
* javelin-util
* javelin-dom
* javelin-request
*/
JX.behavior('dark-console', function(config) {

View file

@ -1,6 +1,6 @@
/**
* @provides javelin-behavior-error-log
* @requires javelin-lib-dev
* @requires javelin-dom
*/
var current_details = null;

View file

@ -1,6 +1,10 @@
/**
* @provides javelin-behavior-phabricator-object-selector
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-dom
* javelin-request
* javelin-util
* javelin-stratcom
*/
JX.behavior('phabricator-object-selector', function(config) {

View file

@ -1,6 +1,10 @@
/**
* @provides javelin-behavior-aphront-basic-tokenizer
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-typeahead
* javelin-tokenizer
* javelin-typeahead-preloaded-source
* javelin-dom
*/
JX.behavior('aphront-basic-tokenizer', function(config) {
@ -10,7 +14,7 @@ JX.behavior('aphront-basic-tokenizer', function(config) {
var typeahead = new JX.Typeahead(
root,
JX.DOM.find(root, 'input', 'tokenizer'));
JX.DOM.find(root, 'input', 'tokenizer-input'));
typeahead.setDatasource(datasource);
var tokenizer = new JX.Tokenizer(root);

View file

@ -1,6 +1,8 @@
/**
* @provides javelin-behavior-workflow
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-stratcom
* javelin-workflow
*/
JX.behavior('workflow', function() {

View file

@ -1,6 +1,10 @@
/**
* @provides javelin-behavior-differential-add-reviewers
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-dom
* javelin-tokenizer
* javelin-typeahead
* javelin-typeahead-preloaded-source
*/
JX.behavior('differential-add-reviewers', function(config) {

View file

@ -1,6 +1,10 @@
/**
* @provides javelin-behavior-differential-feedback-preview
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
* javelin-request
* javelin-util
*/
JX.behavior('differential-feedback-preview', function(config) {
@ -28,7 +32,7 @@ JX.behavior('differential-feedback-preview', function(config) {
cval = content.value;
request = new JX.Request(config.uri, function(r) {
preview && JX.DOM.setContent(preview, JX.HTML(r));
preview && JX.DOM.setContent(preview, JX.$H(r));
min = new Date().getTime() + 500;
defer && defer.stop();
defer = JX.defer(check, 500);
@ -51,7 +55,7 @@ JX.behavior('differential-feedback-preview', function(config) {
function refreshInlinePreview() {
new JX.Request(config.inlineuri, function(r) {
JX.DOM.setContent(JX.$(config.inline), JX.HTML(r));
JX.DOM.setContent(JX.$(config.inline), JX.$H(r));
})
.setTimeout(5000)
.send();

View file

@ -1,6 +1,8 @@
/**
* @provides javelin-behavior-differential-diff-radios
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
*/
JX.behavior('differential-diff-radios', function(config) {

View file

@ -1,6 +1,10 @@
/**
* @provides javelin-behavior-differential-edit-inline-comments
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
* javelin-workflow
* javelin-vector
*/
JX.behavior('differential-edit-inline-comments', function(config) {
@ -27,9 +31,9 @@ JX.behavior('differential-edit-inline-comments', function(config) {
}
var code = target.nextSibling;
var pos = JX.$V(top).add(1 + JX.$V.getDim(target).x, 0);
var dim = JX.$V.getDim(code).add(-4, 0);
dim.y = (JX.$V(bot).y - pos.y) + JX.$V.getDim(bot).y;
var pos = JX.$V(top).add(1 + JX.Vector.getDim(target).x, 0);
var dim = JX.Vector.getDim(code).add(-4, 0);
dim.y = (JX.$V(bot).y - pos.y) + JX.Vector.getDim(bot).y;
pos.setPos(reticle);
dim.setDim(reticle);
@ -48,7 +52,7 @@ JX.behavior('differential-edit-inline-comments', function(config) {
}
function drawInlineComment(table, anchor, r) {
copyRows(table, JX.$N('div', JX.HTML(r.markup)), anchor);
copyRows(table, JX.$N('div', JX.$H(r.markup)), anchor);
finishSelect();
}
@ -245,7 +249,7 @@ JX.behavior('differential-edit-inline-comments', function(config) {
var data = {
op: e.getNode('differential-inline-edit') ? 'edit' : 'delete',
id: e.getNodeData('differential-inline-comment').id,
on_right: e.getNodeData('differential-inline-comment').on_right,
on_right: e.getNodeData('differential-inline-comment').on_right
};
new JX.Workflow(config.uri, data)
.setHandler(function(r) {

View file

@ -1,12 +1,15 @@
/**
* @provides javelin-behavior-differential-populate
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-request
* javelin-util
* javelin-dom
*/
JX.behavior('differential-populate', function(config) {
function onresponse(target, response) {
JX.DOM.replace(JX.$(target), JX.HTML(response));
JX.DOM.replace(JX.$(target), JX.$H(response));
}
for (var k in config.registry) {

View file

@ -1,6 +1,8 @@
/**
* @provides javelin-behavior-differential-show-all-comments
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-stratcom
* javelin-dom
*/
JX.behavior('differential-show-all-comments', function(config) {
@ -11,7 +13,7 @@ JX.behavior('differential-show-all-comments', function(config) {
function(e) {
JX.DOM.setContent(
e.getNode('differential-all-comments-container'),
JX.HTML(config.markup));
JX.$H(config.markup));
e.kill();
});

View file

@ -1,12 +1,16 @@
/**
* @provides javelin-behavior-differential-show-more
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-dom
* javelin-request
* javelin-util
* javelin-stratcom
*/
JX.behavior('differential-show-more', function(config) {
function onresponse(origin, response) {
var div = JX.$N('div', {}, JX.HTML(response));
var div = JX.$N('div', {}, JX.$H(response));
var anchor = origin.getNode('context-target');
var root = anchor.parentNode;
copyRows(root, div, anchor);

View file

@ -1,6 +1,9 @@
/**
* @provides javelin-behavior-diffusion-jump-to
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-util
* javelin-vector
* javelin-dom
*/
JX.behavior('diffusion-jump-to', function(config) {

View file

@ -1,6 +1,9 @@
/**
* @provides javelin-behavior-diffusion-pull-lastmodified
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-dom
* javelin-util
* javelin-request
*/
JX.behavior('diffusion-pull-lastmodified', function(config) {
@ -9,7 +12,7 @@ JX.behavior('diffusion-pull-lastmodified', function(config) {
new JX.Request(uri, JX.bind(config[uri], function(r) {
for (var k in r) {
if (this[k]) {
JX.DOM.setContent(JX.$(this[k]), JX.HTML(r[k]));
JX.DOM.setContent(JX.$(this[k]), JX.$H(r[k]));
}
}
})).send();

View file

@ -1,8 +1,13 @@
/**
* @requires multirow-row-manager
* javelin-lib-dev
* javelin-typeahead-dev
* path-typeahead
* javelin-install
* javelin-typeahead
* javelin-util
* javelin-dom
* javelin-tokenizer
* javelin-typeahead-preloaded-source
* javelin-stratcom
* javelin-json
* @provides herald-rule-editor
* @javelin
*/
@ -257,7 +262,7 @@ JX.install('HeraldRuleEditor', {
_newTokenizer : function(type) {
var template = JX.$N(
'div',
new JX.HTML(this._config.template.markup));
JX.$H(this._config.template.markup));
template = template.firstChild;
template.id = '';

View file

@ -1,6 +1,10 @@
/**
* @requires javelin-lib-dev
* javelin-typeahead-dev
* @requires javelin-install
* javelin-typeahead
* javelin-dom
* javelin-request
* javelin-typeahead-ondemand-source
* javelin-util
* @provides path-typeahead
* @javelin
*/

View file

@ -1,6 +1,6 @@
/**
* @requires herald-rule-editor
* javelin-lib-dev
* javelin-behavior
* @provides javelin-behavior-herald-rule-editor
* @javelin
*/

View file

@ -1,6 +1,10 @@
/**
* @provides javelin-behavior-maniphest-transaction-controls
* @requires javelin-lib-dev
* @requires javelin-behavior
* javelin-dom
* javelin-tokenizer
* javelin-typeahead
* javelin-typeahead-preloaded-source
*/
JX.behavior('maniphest-transaction-controls', function(config) {
@ -51,31 +55,5 @@ JX.behavior('maniphest-transaction-controls', function(config) {
}
});
/*
var root = JX.$(config.tokenizer);
var datasource = new JX.TypeaheadPreloadedSource(config.src);
var typeahead = new JX.Typeahead(root);
typeahead.setDatasource(datasource);
var tokenizer = new JX.Tokenizer(root);
tokenizer.setTypeahead(typeahead);
tokenizer.start();
JX.DOM.listen(
JX.$(config.select),
'change',
null,
function(e) {
if (JX.$(config.select).value == 'add_reviewers') {
JX.DOM.show(JX.$(config.row));
tokenizer.refresh();
} else {
JX.DOM.hide(JX.$(config.row));
}
});
*/
});

View file

@ -1,8 +1,9 @@
/**
* @requires multirow-row-manager
* javelin-lib-dev
* javelin-typeahead-dev
* javelin-install
* path-typeahead
* javelin-dom
* javelin-util
* @provides owners-path-editor
* @javelin
*/
@ -105,7 +106,7 @@ JX.install('OwnersPathEditor', {
var repo_cell = JX.$N('td', {}, repo_select);
var typeahead_cell = JX.$N(
'td',
JX.HTML(this._inputTemplate));
JX.$H(this._inputTemplate));
// Text input for path.
var path_input = JX.DOM.find(typeahead_cell, 'input');
@ -113,7 +114,7 @@ JX.install('OwnersPathEditor', {
path_input,
{
value : path_ref.path || "",
name : "path[" + this._count + "]",
name : "path[" + this._count + "]"
});
// The Typeahead requires a display div called hardpoint.

View file

@ -1,6 +1,6 @@
/**
* @requires owners-path-editor
* javelin-lib-dev
* javelin-behavior
* @provides javelin-behavior-owners-path-editor
* @javelin
*/

1
webroot/rsrc/js/javelin Symbolic link
View file

@ -0,0 +1 @@
../../../externals/javelin/src/

View file

@ -1,179 +0,0 @@
/**
* Javelin core; installs Javelin and Stratcom event delegation.
*
* @provides javelin-magical-init
* @nopackage
*
* @javelin-installs JX.__rawEventQueue
* @javelin-installs JX.__simulate
* @javelin-installs JX.enableDispatch
* @javelin-installs JX.onload
*
* @javelin
*/
(function() {
if (window.JX) {
return;
}
window.JX = {};
window['__DEV__'] = window['__DEV__'] || 0;
var loaded = false;
var onload = [];
var master_event_queue = [];
var root = document.documentElement;
var has_add_event_listener = !!root.addEventListener;
JX.__rawEventQueue = function(what) {
master_event_queue.push(what);
// Evade static analysis - JX.Stratcom
var Stratcom = JX['Stratcom'];
if (Stratcom && Stratcom.ready) {
// Empty the queue now so that exceptions don't cause us to repeatedly
// try to handle events.
var local_queue = master_event_queue;
master_event_queue = [];
for (var ii = 0; ii < local_queue.length; ++ii) {
var evt = local_queue[ii];
// Sometimes IE gives us events which throw when ".type" is accessed;
// just ignore them since we can't meaningfully dispatch them. TODO:
// figure out where these are coming from.
try { var test = evt.type; } catch (x) { continue; }
if (!loaded && evt.type == 'domready') {
document.body && (document.body.id = null);
loaded = true;
for (var ii = 0; ii < onload.length; ii++) {
onload[ii]();
}
}
Stratcom.dispatch(evt);
}
} else {
var target = what.srcElement || what.target;
if (target &&
(what.type in {click: 1, submit: 1}) &&
target.getAttribute &&
target.getAttribute('data-mustcapture') === '1') {
what.returnValue = false;
what.preventDefault && what.preventDefault();
document.body.id = 'event_capture';
// For versions of IE that use attachEvent, the event object is somehow
// stored globally by reference, and all the references we push to the
// master_event_queue will always refer to the most recent event. We
// work around this by popping the useless global event off the queue,
// and pushing a clone of the event that was just fired using the IE's
// proprietary createEventObject function.
// see: http://msdn.microsoft.com/en-us/library/ms536390(v=vs.85).aspx
if (!add_event_listener && document.createEventObject) {
master_event_queue.pop();
master_event_queue.push(document.createEventObject(what));
}
return false;
}
}
}
JX.enableDispatch = function(target, type) {
if (target.addEventListener) {
target.addEventListener(type, JX.__rawEventQueue, true);
} else if (target.attachEvent) {
target.attachEvent('on' + type, JX.__rawEventQueue);
}
};
var document_events = [
'click',
'change',
'keypress',
'mousedown',
'mouseover',
'mouseout',
'mouseup',
'keydown',
'drop',
'dragenter',
'dragleave',
'dragover'
];
// Simulate focus and blur in old versions of IE using focusin and focusout
// TODO: Document the gigantic IE mess here with focus/blur.
// TODO: beforeactivate/beforedeactivate?
// http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
if (!has_add_event_listener) {
document_events.push('focusin', 'focusout');
}
// Opera is multilol: it propagates focus / blur odd, and submit differently
if (window.opera) {
document_events.push('focus', 'blur');
} else {
document_events.push('submit');
}
for (var ii = 0; ii < document_events.length; ++ii) {
JX.enableDispatch(root, document_events[ii]);
}
// In particular, we're interested in capturing window focus/blur here so
// long polls can abort when the window is not focused.
var window_events = [
('onpagehide' in window) ? 'pagehide' : 'unload',
'resize',
'focus',
'blur'
];
for (var ii = 0; ii < window_events.length; ++ii) {
JX.enableDispatch(window, window_events[ii]);
}
JX.__simulate = function(node, event) {
if (!has_add_event_listener) {
var e = {target: node, type: event};
JX.__rawEventQueue(e);
if (e.returnValue === false) {
return false;
}
}
};
if (has_add_event_listener) {
document.addEventListener('DOMContentLoaded', function() {
JX.__rawEventQueue({type: 'domready'});
}, true);
} else {
var ready =
"if (this.readyState == 'complete') {" +
"JX.__rawEventQueue({type: 'domready'});" +
"}";
document.write(
'<script' +
' defer="defer"' +
' src="javascript:void(0)"' +
' onreadystatechange="' + ready + '"' +
'><\/sc' + 'ript\>');
}
JX.onload = function(func) {
if (loaded) {
func();
} else {
onload.push(func);
}
}
})();

View file

@ -1,2 +0,0 @@
/** @provides javelin-init-prod */
(function(){if(window.JX)return;window.JX={};window.__DEV__=window.__DEV__||0;var d=false;var f=[];var e=[];var h=document.documentElement;var b=!!h.addEventListener;JX.__rawEventQueue=function(o){e.push(o);var j=JX.Stratcom;if(j&&j.ready){var m=e;e=[];for(var l=0;l<m.length;++l){var k=m[l];try{var test=k.type;}catch(p){continue;}if(!d&&k.type=='domready'){document.body&&(document.body.id=null);d=true;for(var l=0;l<f.length;l++)f[l]();}j.dispatch(k);}}else{var n=o.srcElement||o.target;if(n&&(o.type in {click:1,submit:1})&&n.getAttribute&&n.getAttribute('data-mustcapture')==='1'){o.returnValue=false;o.preventDefault&&o.preventDefault();document.body.id='event_capture';if(!add_event_listener&&document.createEventObject){e.pop();e.push(document.createEventObject(o));}return false;}}};JX.enableDispatch=function(j,k){if(j.addEventListener){j.addEventListener(k,JX.__rawEventQueue,true);}else if(j.attachEvent)j.attachEvent('on'+k,JX.__rawEventQueue);};var a=['click','change','keypress','mousedown','mouseover','mouseout','mouseup','keydown','drop','dragenter','dragleave','dragover'];if(!b)a.push('focusin','focusout');if(window.opera){a.push('focus','blur');}else a.push('submit');for(var c=0;c<a.length;++c)JX.enableDispatch(h,a[c]);var i=[('onpagehide' in window)?'pagehide':'unload','resize','focus','blur'];for(var c=0;c<i.length;++c)JX.enableDispatch(window,i[c]);JX.__simulate=function(k,event){if(!b){var j={target:k,type:event};JX.__rawEventQueue(j);if(j.returnValue===false)return false;}};if(b){document.addEventListener('DOMContentLoaded',function(){JX.__rawEventQueue({type:'domready'});},true);}else{var g="if (this.readyState == 'complete') {"+"JX.__rawEventQueue({type: 'domready'});"+"}";document.write('<script'+' defer="defer"'+' src="javascript:void(0)"'+' onreadystatechange="'+g+'"'+'><\/sc'+'ript\>');}JX.onload=function(j){if(d){j();}else f.push(j);};})();

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1,242 +0,0 @@
/** @provides javelin-workflow-dev */
/**
* @requires javelin-install javelin-vector javelin-dom
* @provides javelin-mask
* @javelin
*/
/**
* Show a transparent "mask" over the page; used by Workflow to draw visual
* attention to modal dialogs.
*/
JX.install('Mask', {
statics : {
_depth : 0,
_mask : null,
show : function() {
if (!JX.Mask._depth) {
JX.Mask._mask = JX.$N('div', {className: 'jx-mask'});
document.body.appendChild(JX.Mask._mask);
JX.$V.getDocument().setDim(JX.Mask._mask);
}
++JX.Mask._depth;
},
hide : function() {
--JX.Mask._depth;
if (!JX.Mask._depth) {
JX.DOM.remove(JX.Mask._mask);
JX.Mask._mask = null;
}
}
}
});
/**
* @requires javelin-stratcom
* javelin-request
* javelin-dom
* javelin-vector
* javelin-install
* javelin-util
* javelin-mask
* @provides javelin-workflow
* @javelin
*/
JX.install('Workflow', {
construct : function(uri, data) {
if (__DEV__) {
if (!uri || uri == '#') {
throw new Error(
'new JX.Workflow(<?>, ...): '+
'bogus URI provided when creating workflow.');
}
}
this.setURI(uri);
this.setData(data || {});
},
events : ['error', 'finally', 'submit'],
statics : {
_stack : [],
newFromForm : function(form, data) {
var inputs = [].concat(
JX.DOM.scry(form, 'input'),
JX.DOM.scry(form, 'button'),
JX.DOM.scry(form, 'textarea'));
for (var ii = 0; ii < inputs.length; ii++) {
if (inputs[ii].disabled) {
delete inputs[ii];
} else {
inputs[ii].disabled = true;
}
}
var workflow = new JX.Workflow(
form.getAttribute('action'),
JX.copy(data || {}, JX.DOM.serialize(form)));
workflow.setMethod(form.getAttribute('method'));
workflow.listen('finally', function() {
for (var ii = 0; ii < inputs.length; ii++) {
inputs[ii] && (inputs[ii].disabled = false);
}
});
return workflow;
},
newFromLink : function(link) {
var workflow = new JX.Workflow(link.href);
return workflow;
},
_push : function(workflow) {
JX.Mask.show();
JX.Workflow._stack.push(workflow);
},
_pop : function() {
var dialog = JX.Workflow._stack.pop();
(dialog.getCloseHandler() || JX.bag)();
dialog._destroy();
JX.Mask.hide();
},
disable : function() {
JX.Workflow._disabled = true;
},
_onbutton : function(event) {
if (JX.Stratcom.pass()) {
return;
}
if (JX.Workflow._disabled) {
return;
}
var t = event.getTarget();
if (t.name == '__cancel__' || t.name == '__close__') {
JX.Workflow._pop();
} else {
var form = event.getNode('jx-dialog');
var data = JX.DOM.serialize(form);
data[t.name] = true;
data.__wflow__ = true;
var active = JX.Workflow._stack[JX.Workflow._stack.length - 1];
var e = active.invoke('submit', {form: form, data: data});
if (!e.getStopped()) {
active._destroy();
active
.setURI(form.getAttribute('action') || active.getURI())
.setData(data)
.start();
}
}
event.prevent();
}
},
members : {
_root : null,
_pushed : false,
_onload : function(r) {
// It is permissible to send back a falsey redirect to force a page
// reload, so we need to take this branch if the key is present.
if (r && (typeof r.redirect != 'undefined')) {
JX.go(r.redirect, true);
} else if (r && r.dialog) {
this._push();
this._root = JX.$N(
'div',
{className: 'jx-client-dialog'},
JX.HTML(r.dialog));
JX.DOM.listen(
this._root,
'click',
[['jx-workflow-button'], ['tag:button']],
JX.Workflow._onbutton);
document.body.appendChild(this._root);
var d = JX.$V.getDim(this._root);
var v = JX.$V.getViewport();
var s = JX.$V.getScroll();
JX.$V((v.x - d.x) / 2, s.y + 100).setPos(this._root);
try {
try {
JX.DOM.focus(JX.DOM.find(this._root, 'button', '__default__'));
} catch (_ignored) {}
var inputs = JX.DOM.scry(this._root, 'input')
.concat(JX.DOM.scry(this._root, 'textarea'));
var miny = Number.POSITIVE_INFINITY;
var target = null;
for (var ii = 0; ii < inputs.length; ++ii) {
if (inputs[ii].type != 'hidden') {
// Find the topleft-most displayed element.
var p = JX.$V(inputs[ii]);
if (p.y < miny) {
miny = p.y;
target = inputs[ii];
}
}
}
target && JX.DOM.focus(target);
} catch (_ignored) {}
} else if (this.getHandler()) {
this.getHandler()(r);
this._pop();
} else if (r) {
if (__DEV__) {
throw new Error('Response to workflow request went unhandled.');
}
}
},
_push : function() {
if (!this._pushed) {
this._pushed = true;
JX.Workflow._push(this);
}
},
_pop : function() {
if (this._pushed) {
this._pushed = false;
JX.Workflow._pop();
}
},
_destroy : function() {
if (this._root) {
JX.DOM.remove(this._root);
this._root = null;
}
},
start : function() {
var uri = this.getURI();
var method = this.getMethod();
var r = new JX.Request(uri, JX.bind(this, this._onload));
r.setData(this.getData());
r.setDataSerializer(this.getDataSerializer());
if (method) {
r.setMethod(method);
}
r.listen('finally', JX.bind(this, this.invoke, 'finally'));
r.listen('error', JX.bind(this, function(error) {
var e = this.invoke('error', error);
if (e.getStopped()) {
return;
}
// TODO: Default error behavior? On Facebook Lite, we just shipped the
// user to "/error/". We could emit a blanket 'workflow-failed' type
// event instead.
}));
r.send();
}
},
properties : {
handler : null,
closeHandler : null,
data : null,
dataSerializer : null,
method : null,
URI : null
}
});

View file

@ -1,3 +0,0 @@
/** @provides javelin-workflow-prod */
JX.install('Mask',{statics:{_a:0,_b:null,show:function(){if(!JX.Mask._a){JX.Mask._b=JX.$N('div',{className:'jx-mask'});document.body.appendChild(JX.Mask._b);JX.$V.getDocument().setDim(JX.Mask._b);}++JX.Mask._a;},hide:function(){--JX.Mask._a;if(!JX.Mask._a){JX.DOM.remove(JX.Mask._b);JX.Mask._b=null;}}}});JX.install('Workflow',{construct:function(b,a){this.setURI(b);this.setData(a||{});},events:['error','finally','submit'],statics:{_c:[],newFromForm:function(b,a){var d=[].concat(JX.DOM.scry(b,'input'),JX.DOM.scry(b,'button'),JX.DOM.scry(b,'textarea'));for(var c=0;c<d.length;c++)if(d[c].disabled){delete d[c];}else d[c].disabled=true;var e=new JX.Workflow(b.getAttribute('action'),JX.copy(a||{},JX.DOM.serialize(b)));e.setMethod(b.getAttribute('method'));e.listen('finally',function(){for(var f=0;f<d.length;f++)d[f]&&(d[f].disabled=false);});return e;},newFromLink:function(a){var b=new JX.Workflow(a.href);return b;},_d:function(a){JX.Mask.show();JX.Workflow._c.push(a);},_e:function(){var a=JX.Workflow._c.pop();(a.getCloseHandler()||JX.bag)();a._f();JX.Mask.hide();},disable:function(){JX.Workflow._g=true;},_h:function(event){if(JX.Stratcom.pass())return;if(JX.Workflow._g)return;var e=event.getTarget();if(e.name=='__cancel__'||e.name=='__close__'){JX.Workflow._e();}else{var d=event.getNode('jx-dialog');var b=JX.DOM.serialize(d);b[e.name]=true;b.__wflow__=true;var a=JX.Workflow._c[JX.Workflow._c.length-1];var c=a.invoke('submit',{form:d,data:b});if(!c.getStopped()){a._f();a.setURI(d.getAttribute('action')||a.getURI()).setData(b).start();}}event.prevent();}},members:{_i:null,_j:false,_k:function(c){if(c&&(typeof c.redirect!='undefined')){JX.go(c.redirect,true);}else if(c&&c.dialog){this._d();this._i=JX.$N('div',{className:'jx-client-dialog'},JX.HTML(c.dialog));JX.DOM.listen(this._i,'click','tag:button',JX.Workflow._h);document.body.appendChild(this._i);var b=JX.$V.getDim(this._i);var e=JX.$V.getViewport();var d=JX.$V.getScroll();JX.$V((e.x-b.x)/2,d.y+100).setPos(this._i);try{JX.DOM.focus(JX.DOM.find(this._i,'button','__default__'));var inputs=JX.DOM.scry(this._i,'input').concat(JX.DOM.scry(this._i,'textarea'));var miny=Number.POSITIVE_INFINITY;var target=null;for(var ii=0;ii<inputs.length;++ii)if(inputs[ii].type!='hidden'){var p=JX.$V(inputs[ii]);if(p.y<miny){miny=p.y;target=inputs[ii];}}target&&JX.DOM.focus(target);}catch(a){}}else if(this.getHandler()){this.getHandler()(c);this._e();}},_d:function(){if(!this._j){this._j=true;JX.Workflow._d(this);}},_e:function(){if(this._j){this._j=false;JX.Workflow._e();}},_f:function(){if(this._i){JX.DOM.remove(this._i);this._i=null;}},start:function(){var c=this.getURI();var a=this.getMethod();var b=new JX.Request(c,JX.bind(this,this._k));b.setData(this.getData());b.setDataSerializer(this.getDataSerializer());if(a)b.setMethod(a);b.listen('finally',JX.bind(this,this.invoke,'finally'));b.listen('error',JX.bind(this,function(e){var d=this.invoke('error',e);if(d.getStopped())return;}));b.send();}},properties:{handler:null,closeHandler:null,data:null,dataSerializer:null,method:null,URI:null}});