[Jifty-commit] r3711 - in jifty/branches/autoversioning: . debian doc/talks examples/Example-Todo examples/Yada/etc examples/Yada/inc/Module examples/Yada/inc/Module/Install examples/Yada/lib/Yada examples/Yada/lib/Yada/Action examples/Yada/lib/Yada/Model examples/Yada/lib/Yada/View examples/Yada/t inc/Module inc/Module/Install lib lib/Jifty lib/Jifty/Action lib/Jifty/Action/Record lib/Jifty/Event lib/Jifty/Manual lib/Jifty/Mason lib/Jifty/Model lib/Jifty/Module lib/Jifty/Plugin lib/Jifty/Plugin/ActorMetadata lib/Jifty/Plugin/ActorMetadata/Mixin lib/Jifty/Plugin/ActorMetadata/Mixin/Model lib/Jifty/Plugin/Authentication lib/Jifty/Plugin/Authentication/Facebook lib/Jifty/Plugin/Authentication/Facebook/Action lib/Jifty/Plugin/Authentication/Facebook/Mixin lib/Jifty/Plugin/Authentication/Facebook/Mixin/Model lib/Jifty/Plugin/Authentication/Password lib/Jifty/Plugin/Authentication/Password/Action lib/Jifty/Plugin/Authentication/Password/Mixin/Model lib/Jifty/Plugin/CompressedCSSandJS lib/Jifty/Plugin/Debug lib/Jifty/Plugin/ErrorTemplates lib/Jifty/Plugin/Feedback lib/Jifty/Plugin/Feedback/Action lib/Jifty/Plugin/GoogleMap lib/Jifty/Plugin/OpenID lib/Jifty/Plugin/OpenID/Action lib/Jifty/Plugin/OpenID/Mixin lib/Jifty/Plugin/OpenID/Mixin/Model lib/Jifty/Plugin/REST lib/Jifty/Plugin/SinglePage lib/Jifty/Plugin/SiteNews lib/Jifty/Plugin/SiteNews/Mixin/Model lib/Jifty/Plugin/SiteNews/View lib/Jifty/Plugin/SkeletonApp lib/Jifty/Plugin/TabView lib/Jifty/Plugin/User/Mixin/Model lib/Jifty/Plugin/Userpic lib/Jifty/Request lib/Jifty/Script lib/Jifty/Subs lib/Jifty/Test/WWW lib/Jifty/Upgrade lib/Jifty/View lib/Jifty/View/Declare lib/Jifty/View/Mason lib/Jifty/View/Static lib/Jifty/Web lib/Jifty/Web/Form lib/Jifty/Web/Form/Field plugins/CodePress plugins/CodePress/doc plugins/CodePress/lib plugins/CodePress/lib/Jifty plugins/CodePress/lib/Jifty/Plugin plugins/CodePress/lib/Jifty/Plugin/CodePress plugins/CodePress/lib/Jifty/Plugin/CodePress/Model plugins/CodePress/share plugins/CodePress/share/po plugins/CodePress/share/web plugins/CodePress/share/web/static plugins/CodePress/share/web/static/codepress plugins/CodePress/share/web/static/codepress/engines plugins/CodePress/share/web/static/codepress/images plugins/CodePress/share/web/static/codepress/languages plugins/CodePress/share/web/static/js plugins/CodePress/t share/plugins/Jifty/Plugin/AdminUI/web/templates/__jifty/admin share/plugins/Jifty/Plugin/GoogleMap share/plugins/Jifty/Plugin/GoogleMap/web share/plugins/Jifty/Plugin/GoogleMap/web/static share/plugins/Jifty/Plugin/GoogleMap/web/static/css share/plugins/Jifty/Plugin/GoogleMap/web/static/js share/po share/web/static/js share/web/static/js/yui share/web/templates/__jifty/webservices share/web/templates/_elements t/Mapper/lib/Mapper/Action t/Mapper/share/web/templates t/Mapper/t t/TestApp-Plugin-AppPluginHasModels t/TestApp-Plugin-AppPluginHasModels/bin t/TestApp-Plugin-AppPluginHasModels/doc t/TestApp-Plugin-AppPluginHasModels/etc t/TestApp-Plugin-AppPluginHasModels/lib t/TestApp-Plugin-AppPluginHasModels/lib/TestApp t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Action t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Model t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model t/TestApp-Plugin-AppPluginHasModels/log t/TestApp-Plugin-AppPluginHasModels/share t/TestApp-Plugin-AppPluginHasModels/share/po t/TestApp-Plugin-AppPluginHasModels/share/web t/TestApp-Plugin-AppPluginHasModels/share/web/static t/TestApp-Plugin-AppPluginHasModels/share/web/templates t/TestApp-Plugin-AppPluginHasModels/t t/TestApp-Plugin-AppPluginHasModels/var t/TestApp-Plugin-AppPluginHasModels/var/mason t/TestApp-Plugin-AppPluginHasModels/var/mason/cache t/TestApp-Plugin-AppPluginHasModels/var/mason/obj t/TestApp/lib/TestApp t/TestApp/lib/TestApp/View t/TestApp/share/web/templates/dispatch t/TestApp/t

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Sun Jul 22 21:14:06 EDT 2007


Author: jesse
Date: Sun Jul 22 21:13:55 2007
New Revision: 3711

Added:
   jifty/branches/autoversioning/examples/Yada/
      - copied from r3297, /jifty/branches/autoversioning/examples/Example-Todo/
   jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Can.pm
   jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Fetch.pm
   jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Makefile.pm
   jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Win32.pm
   jifty/branches/autoversioning/examples/Yada/lib/Yada/
   jifty/branches/autoversioning/examples/Yada/lib/Yada/Action/
   jifty/branches/autoversioning/examples/Yada/lib/Yada/Model/
   jifty/branches/autoversioning/examples/Yada/lib/Yada/Model/Todo.pm
   jifty/branches/autoversioning/examples/Yada/lib/Yada/Model/User.pm
   jifty/branches/autoversioning/examples/Yada/lib/Yada/View/
   jifty/branches/autoversioning/examples/Yada/lib/Yada/View.pm
   jifty/branches/autoversioning/examples/Yada/lib/Yada/View/Todo.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata/
   jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata/Mixin/
   jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata/Mixin/Model/
   jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata/Mixin/Model/ActorMetadata.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Action/
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Mixin/
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Mixin/Model/
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Mixin/Model/User.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/View.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Debug/
   jifty/branches/autoversioning/lib/Jifty/Plugin/Debug.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Debug/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Feedback/
   jifty/branches/autoversioning/lib/Jifty/Plugin/Feedback.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Feedback/Action/
   jifty/branches/autoversioning/lib/Jifty/Plugin/Feedback/Action/SendFeedback.pm   (contents, props changed)
   jifty/branches/autoversioning/lib/Jifty/Plugin/Feedback/View.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/GoogleMap/
   jifty/branches/autoversioning/lib/Jifty/Plugin/GoogleMap.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/GoogleMap/Widget.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Mixin/
   jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Mixin/Model/
   jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Mixin/Model/User.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/View.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/SinglePage/
   jifty/branches/autoversioning/lib/Jifty/Plugin/SinglePage.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/SinglePage/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/TabView/
   jifty/branches/autoversioning/lib/Jifty/Plugin/TabView/View.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic/
   jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic/View.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic/Widget.pm
   jifty/branches/autoversioning/lib/Jifty/View.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare/Page.pm
   jifty/branches/autoversioning/plugins/CodePress/
   jifty/branches/autoversioning/plugins/CodePress/Makefile.PL
   jifty/branches/autoversioning/plugins/CodePress/doc/
   jifty/branches/autoversioning/plugins/CodePress/doc/index.html
   jifty/branches/autoversioning/plugins/CodePress/lib/
   jifty/branches/autoversioning/plugins/CodePress/lib/Jifty/
   jifty/branches/autoversioning/plugins/CodePress/lib/Jifty/Plugin/
   jifty/branches/autoversioning/plugins/CodePress/lib/Jifty/Plugin/CodePress/
   jifty/branches/autoversioning/plugins/CodePress/lib/Jifty/Plugin/CodePress.pm
   jifty/branches/autoversioning/plugins/CodePress/lib/Jifty/Plugin/CodePress/Model/
   jifty/branches/autoversioning/plugins/CodePress/lib/Jifty/Plugin/CodePress/Textarea.pm
   jifty/branches/autoversioning/plugins/CodePress/share/
   jifty/branches/autoversioning/plugins/CodePress/share/po/
   jifty/branches/autoversioning/plugins/CodePress/share/web/
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/codepress.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/codepress.html
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/gecko.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/khtml.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/msie.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/older.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/opera.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/images/
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/images/line-numbers.png   (contents, props changed)
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/asp.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/asp.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/csharp.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/csharp.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/css.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/css.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/generic.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/generic.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/html.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/html.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/java.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/java.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/javascript.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/javascript.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/perl.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/perl.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/php.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/php.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/ruby.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/ruby.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/sql.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/sql.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/text.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/text.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/vbscript.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/vbscript.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/xsl.css
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/xsl.js
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/js/
   jifty/branches/autoversioning/plugins/CodePress/share/web/static/js/codepress.js
   jifty/branches/autoversioning/plugins/CodePress/t/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/GoogleMap/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/GoogleMap/web/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/GoogleMap/web/static/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/GoogleMap/web/static/css/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/GoogleMap/web/static/css/google_map.css
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/GoogleMap/web/static/js/
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/GoogleMap/web/static/js/google_map.js
   jifty/branches/autoversioning/share/web/static/js/yui/oom_select.patch
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/Makefile.PL
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/bin/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/bin/jifty   (contents, props changed)
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/doc/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/etc/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/etc/config.yml
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Action/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Model/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin.pm
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model/Color.pm
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/log/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/share/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/share/po/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/share/web/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/share/web/static/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/share/web/templates/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/t/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/t/plugin-model.t
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/var/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/var/mason/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/var/mason/cache/
   jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/var/mason/obj/
   jifty/branches/autoversioning/t/TestApp/share/web/templates/dispatch/protocol
   jifty/branches/autoversioning/t/TestApp/t/02-dispatch-http.t
   jifty/branches/autoversioning/t/TestApp/t/02-dispatch-https.t
   jifty/branches/autoversioning/t/TestApp/t/16-template-region.t
   jifty/branches/autoversioning/t/TestApp/t/17-template-region-internal-redirect.t
Removed:
   jifty/branches/autoversioning/doc/talks/
   jifty/branches/autoversioning/examples/Example-Todo/
Modified:
   jifty/branches/autoversioning/   (props changed)
   jifty/branches/autoversioning/AUTHORS
   jifty/branches/autoversioning/META.yml
   jifty/branches/autoversioning/Makefile.PL
   jifty/branches/autoversioning/debian/control
   jifty/branches/autoversioning/examples/Yada/META.yml
   jifty/branches/autoversioning/examples/Yada/Makefile.PL
   jifty/branches/autoversioning/examples/Yada/etc/config.yml
   jifty/branches/autoversioning/examples/Yada/inc/Module/Install.pm
   jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Base.pm
   jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Metadata.pm
   jifty/branches/autoversioning/examples/Yada/inc/Module/Install/WriteAll.pm
   jifty/branches/autoversioning/examples/Yada/t/00-model-Todo.t
   jifty/branches/autoversioning/inc/Module/Install.pm
   jifty/branches/autoversioning/inc/Module/Install/AutoInstall.pm
   jifty/branches/autoversioning/inc/Module/Install/Base.pm
   jifty/branches/autoversioning/inc/Module/Install/Can.pm
   jifty/branches/autoversioning/inc/Module/Install/Fetch.pm
   jifty/branches/autoversioning/inc/Module/Install/Include.pm
   jifty/branches/autoversioning/inc/Module/Install/Makefile.pm
   jifty/branches/autoversioning/inc/Module/Install/Metadata.pm
   jifty/branches/autoversioning/inc/Module/Install/Scripts.pm
   jifty/branches/autoversioning/inc/Module/Install/Share.pm
   jifty/branches/autoversioning/inc/Module/Install/Win32.pm
   jifty/branches/autoversioning/inc/Module/Install/WriteAll.pm
   jifty/branches/autoversioning/lib/Jifty.pm
   jifty/branches/autoversioning/lib/Jifty/API.pm
   jifty/branches/autoversioning/lib/Jifty/Action.pm
   jifty/branches/autoversioning/lib/Jifty/Action/Record.pm
   jifty/branches/autoversioning/lib/Jifty/Action/Record/Search.pm
   jifty/branches/autoversioning/lib/Jifty/ClassLoader.pm
   jifty/branches/autoversioning/lib/Jifty/Config.pm
   jifty/branches/autoversioning/lib/Jifty/Continuation.pm
   jifty/branches/autoversioning/lib/Jifty/CurrentUser.pm
   jifty/branches/autoversioning/lib/Jifty/DateTime.pm
   jifty/branches/autoversioning/lib/Jifty/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Event.pm
   jifty/branches/autoversioning/lib/Jifty/Event/Model.pm
   jifty/branches/autoversioning/lib/Jifty/I18N.pm
   jifty/branches/autoversioning/lib/Jifty/LetMe.pm
   jifty/branches/autoversioning/lib/Jifty/Manual/Continuations.pod
   jifty/branches/autoversioning/lib/Jifty/Manual/Cookbook.pod
   jifty/branches/autoversioning/lib/Jifty/Mason/Halo.pm
   jifty/branches/autoversioning/lib/Jifty/Model/SessionCollection.pm
   jifty/branches/autoversioning/lib/Jifty/Module/Pluggable.pm
   jifty/branches/autoversioning/lib/Jifty/Notification.pm
   jifty/branches/autoversioning/lib/Jifty/Object.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/View.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/CompressedCSSandJS.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/CompressedCSSandJS/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/ErrorTemplates/View.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Action/CreateOpenIDUser.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/REST/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/Dispatcher.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/Mixin/Model/News.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/View/News.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/SkeletonApp/View.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/User.pm
   jifty/branches/autoversioning/lib/Jifty/Plugin/User/Mixin/Model/User.pm
   jifty/branches/autoversioning/lib/Jifty/Record.pm
   jifty/branches/autoversioning/lib/Jifty/Request.pm
   jifty/branches/autoversioning/lib/Jifty/Request/Mapper.pm
   jifty/branches/autoversioning/lib/Jifty/RightsFrom.pm
   jifty/branches/autoversioning/lib/Jifty/Schema.pm
   jifty/branches/autoversioning/lib/Jifty/Script.pm
   jifty/branches/autoversioning/lib/Jifty/Script/App.pm
   jifty/branches/autoversioning/lib/Jifty/Script/Deps.pm
   jifty/branches/autoversioning/lib/Jifty/Script/Plugin.pm
   jifty/branches/autoversioning/lib/Jifty/Script/Schema.pm
   jifty/branches/autoversioning/lib/Jifty/Script/Server.pm
   jifty/branches/autoversioning/lib/Jifty/Server.pm
   jifty/branches/autoversioning/lib/Jifty/Subs.pm
   jifty/branches/autoversioning/lib/Jifty/Subs/Render.pm
   jifty/branches/autoversioning/lib/Jifty/Test.pm
   jifty/branches/autoversioning/lib/Jifty/Test/WWW/Mechanize.pm
   jifty/branches/autoversioning/lib/Jifty/Upgrade.pm
   jifty/branches/autoversioning/lib/Jifty/Upgrade/Internal.pm
   jifty/branches/autoversioning/lib/Jifty/Util.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare/BaseClass.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare/CRUD.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare/CoreTemplates.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare/Handler.pm
   jifty/branches/autoversioning/lib/Jifty/View/Declare/Helpers.pm
   jifty/branches/autoversioning/lib/Jifty/View/Mason/Handler.pm
   jifty/branches/autoversioning/lib/Jifty/View/Static/Handler.pm
   jifty/branches/autoversioning/lib/Jifty/Web.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Clickable.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Element.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Button.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Checkbox.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Combobox.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Date.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Hidden.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/InlineButton.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Password.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Radio.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/ResetButton.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Select.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Text.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Textarea.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Unrendered.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Upload.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Form/Link.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Menu.pm
   jifty/branches/autoversioning/lib/Jifty/Web/PageRegion.pm
   jifty/branches/autoversioning/lib/Jifty/Web/Session.pm
   jifty/branches/autoversioning/share/plugins/Jifty/Plugin/AdminUI/web/templates/__jifty/admin/index.html
   jifty/branches/autoversioning/share/po/en.po
   jifty/branches/autoversioning/share/po/zh_cn.po
   jifty/branches/autoversioning/share/web/static/js/jifty.js
   jifty/branches/autoversioning/share/web/static/js/key_bindings.js
   jifty/branches/autoversioning/share/web/static/js/yui/calendar.js
   jifty/branches/autoversioning/share/web/templates/__jifty/webservices/xml
   jifty/branches/autoversioning/share/web/templates/_elements/sidebar
   jifty/branches/autoversioning/t/Mapper/lib/Mapper/Action/CrossBridge.pm
   jifty/branches/autoversioning/t/Mapper/share/web/templates/index.html
   jifty/branches/autoversioning/t/Mapper/t/02-api.t
   jifty/branches/autoversioning/t/TestApp/lib/TestApp/Dispatcher.pm
   jifty/branches/autoversioning/t/TestApp/lib/TestApp/View.pm
   jifty/branches/autoversioning/t/TestApp/lib/TestApp/View/base.pm
   jifty/branches/autoversioning/t/TestApp/lib/TestApp/View/instance.pm
   jifty/branches/autoversioning/t/TestApp/t/02-dispatch-show-rule-in-wrong-ruleset.t
   jifty/branches/autoversioning/t/TestApp/t/08-notifications.t
   jifty/branches/autoversioning/t/TestApp/t/15-template-subclass.t

Log:
 r61113 at 134:  jesse | 2007-07-22 10:26:50 -0700
 


Modified: jifty/branches/autoversioning/AUTHORS
==============================================================================
--- jifty/branches/autoversioning/AUTHORS	(original)
+++ jifty/branches/autoversioning/AUTHORS	Sun Jul 22 21:13:55 2007
@@ -29,3 +29,4 @@
 Marc Mims <marc at questright.com>
 Alexander Klink <alech at cpan.org>
 Andreas Koenig <andreas.koenig.7os6VVqR at franz.ak.mind.de>
+sunnavy <sunnavy at gmail.com>

Modified: jifty/branches/autoversioning/META.yml
==============================================================================
--- jifty/branches/autoversioning/META.yml	(original)
+++ jifty/branches/autoversioning/META.yml	Sun Jul 22 21:13:55 2007
@@ -2,7 +2,7 @@
 build_requires: 
   ExtUtils::MakeMaker: 6.11
 distribution_type: module
-generated_by: Module::Install version 0.650
+generated_by: Module::Install version 0.670
 license: Perl
 meta-spec: 
   url: http://module-build.sourceforge.net/META-spec-v1.3.html
@@ -39,6 +39,7 @@
   Test::HTTP::Server::Simple: 0.02
   Test::MockModule: 0.05
   Test::MockObject: 1.07
+  WWW::Facebook::API: 0.3.6
 requires: 
   App::CLI: 0.03
   CGI: 3.19
@@ -49,6 +50,7 @@
   Class::Accessor: 0
   Class::Container: 0
   Class::Data::Inheritable: 0
+  Class::Trigger: 0
   Compress::Zlib: 0
   Crypt::CBC: 0
   Crypt::Rijndael: 0
@@ -61,6 +63,7 @@
   Email::LocalDelivery: 0
   Email::MIME: 0
   Email::MIME::ContentType: 0
+  Email::MIME::CreateHTML: 0
   Email::MIME::Creator: 0
   Email::Send: 1.99_01
   Email::Simple: 0
@@ -80,15 +83,16 @@
   Hash::Merge: 0
   Hook::LexWrap: 0
   IPC::PubSub: 0.23
+  IPC::Run3: 0
   JSON::Syck: 0.15
-  Jifty::DBI: 0.40
+  Jifty::DBI: 0.42
   LWP::UserAgent: 0
   Locale::Maketext::Extract: 0.20
   Locale::Maketext::Lexicon: 0.60
   Log::Log4perl: 1.04
   MIME::Types: 0
   Module::CoreList: 0
-  Module::Pluggable: 3.1
+  Module::Pluggable: 3.5
   Module::Pluggable::Object: 0
   Module::Refresh: 0
   Module::ScanDeps: 0
@@ -99,8 +103,10 @@
   Scalar::Defer: 0.10
   Shell::Command: 0
   String::Koremutake: 0
-  Template::Declare: 0.07
+  Template::Declare: 0.21
   Test::Base: 0
+  Test::Log4perl: 0
+  Test::LongString: 0
   Test::More: 0.62
   Test::Pod::Coverage: 0
   Test::WWW::Mechanize: 1.04

Modified: jifty/branches/autoversioning/Makefile.PL
==============================================================================
--- jifty/branches/autoversioning/Makefile.PL	(original)
+++ jifty/branches/autoversioning/Makefile.PL	Sun Jul 22 21:13:55 2007
@@ -8,6 +8,7 @@
 requires('Class::Accessor'); # Class::Accessor::Fast
 requires('Class::Container');
 requires('Class::Data::Inheritable');
+requires('Class::Trigger');
 requires('CGI' => '3.19');
 requires('CGI::Cookie::Splitter');
 requires('Crypt::CBC');
@@ -24,6 +25,7 @@
 requires('Email::MIME');
 requires('Email::MIME::Creator');
 requires('Email::MIME::ContentType');
+requires('Email::MIME::CreateHTML');
 requires('Email::Send' => '1.99_01'); # Email::Send::Jifty::Test
 requires('Email::Simple');
 requires('Email::Simple::Creator');
@@ -42,13 +44,14 @@
 requires('Hash::Merge');
 requires('Hook::LexWrap');
 requires('IPC::PubSub' => '0.23' );
-requires('Jifty::DBI' => '0.40' );            # Jifty::DBI::Collection Jifty::DBI::Handle Jifty::DBI::Record::Cachable Jifty::DBI::SchemaGenerator
+requires('IPC::Run3');
+requires('Jifty::DBI' => '0.42' );            # Jifty::DBI::Collection Jifty::DBI::Handle Jifty::DBI::Record::Cachable Jifty::DBI::SchemaGenerator
 requires('Locale::Maketext::Extract' => '0.20');
 requires('Locale::Maketext::Lexicon' => '0.60');
 requires('Log::Log4perl' => '1.04');
 requires('LWP::UserAgent'); # Net::HTTP
 requires('MIME::Types');
-requires('Module::Pluggable' => '3.1'); # Module::Pluggable::Object
+requires('Module::Pluggable' => '3.5'); # Module::Pluggable::Object
 requires('Module::Pluggable::Object');
 requires('Module::CoreList');
 requires('Module::Refresh');
@@ -59,8 +62,10 @@
 requires('Shell::Command');
 requires('String::Koremutake');
 requires('SQL::ReservedWords');
-requires('Template::Declare' => '0.07');                # Template::Declare::Tags
+requires('Template::Declare' => '0.21');                # Template::Declare::Tags
 requires('Test::Base');
+requires('Test::LongString');
+requires('Test::Log4perl');
 requires('Test::More' => 0.62 ),
 requires('Test::Pod::Coverage'),
 requires('Test::WWW::Mechanize' => 1.04 ),
@@ -131,8 +136,12 @@
         recommends('Cache::FileCache'),
         recommends('LWPx::ParanoidAgent'),
     ],
+    'Facebook Login Plugin' => [
+        -default => 0,
+        recommends('WWW::Facebook::API' => '0.3.6'),
+    ],
     'Jifty console' => [
-        -default => 1,
+        -default => 0,
         recommends('Devel::EvalContext')
     ],
 );

Modified: jifty/branches/autoversioning/debian/control
==============================================================================
--- jifty/branches/autoversioning/debian/control	(original)
+++ jifty/branches/autoversioning/debian/control	Sun Jul 22 21:13:55 2007
@@ -53,8 +53,10 @@
  perl-modules, libcgi-cookie-splitter-perl, libcgi-simple-perl,
  libcrypt-cbc-perl, libcrypt-rijndael-perl,
  libcompress-zlib-perl, libcss-squish-perl (>> 0.05), 
+ libclass-trigger-perl, libdevel-evalcontext-perl,
  libdbd-sqlite3-perl, libdata-page-perl, libossp-uuid-perl,
- libdatetime-perl, libdate-manip-perl, libemail-folder-perl,
+ libdatetime-perl, libdatetime-format-builder-perl, 
+ libdate-manip-perl, libemail-folder-perl,
  libemail-localdelivery-perl, libemail-mime-perl,
  libemail-mime-creator-perl, libemail-mime-contenttype-perl,
  libemail-send-perl (>> 1.99_01), libemail-simple-perl,
@@ -64,14 +66,14 @@
  libhtml-lint-perl, libhtml-mason-perl (>> 1.31), 
  libwww-perl, libhttp-server-simple-perl (>> 0.26), 
  libhttp-server-simple-recorder-perl, libhash-merge-perl, libhook-lexwrap-perl,
- libipc-pubsub-perl (>> 0.23), libjifty-dbi-perl (>> 0.40),
- liblocale-maketext-lexicon-perl, liblog-log4perl-perl,
- libmime-types-perl, libmodule-pluggable-perl (>> 3.1),
+ libipc-pubsub-perl (>> 0.23), libjifty-dbi-perl (>> 0.40), libipc-run3-perl,
+ liblocale-maketext-lexicon-perl, liblocale-maketext-simple-perl, liblog-log4perl-perl,
+ libmime-types-perl, libmodule-pluggable-perl (>> 3.5),
  libmodule-corelist-perl, libmodule-refresh-perl,
  libmodule-scandeps-perl, libobject-declare-perl (>> 0.22),
  libparams-validate-perl, libscalar-defer-perl (>> 0.10),
  libstring-koremutake-perl, libsql-reservedwords-perl,
- libtemplate-declare-perl (>> 0.07), 
+ libtemplate-declare-perl (>> 0.21), 
  libtest-base-perl, libuniversal-require-perl, liburi-perl,
  libxml-writer-perl (>> 0.601), libxml-simple-perl,
  libxml-xpath-perl, libversion-perl, libyaml-syck-perl (>> 0.72), 

Modified: jifty/branches/autoversioning/examples/Yada/META.yml
==============================================================================
--- /jifty/branches/autoversioning/examples/Example-Todo/META.yml	(original)
+++ jifty/branches/autoversioning/examples/Yada/META.yml	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,15 @@
+--- 
+distribution_type: module
+generated_by: Module::Install version 0.67
+license: unknown
+meta-spec: 
+  url: http://module-build.sourceforge.net/META-spec-v1.3.html
+  version: 1.3
+name: Yada
+no_index: 
+  directory: 
+    - inc
+    - t
+requires: 
+  Jifty: 0.70117
+version: 0.01

Modified: jifty/branches/autoversioning/examples/Yada/Makefile.PL
==============================================================================
--- /jifty/branches/autoversioning/examples/Example-Todo/Makefile.PL	(original)
+++ jifty/branches/autoversioning/examples/Yada/Makefile.PL	Sun Jul 22 21:13:55 2007
@@ -1,6 +1,6 @@
 use inc::Module::Install;
 
-name        'Example::Todo';
+name        'Yada';
 version     '0.01';
 requires    'Jifty' => '0.70117';
 

Modified: jifty/branches/autoversioning/examples/Yada/etc/config.yml
==============================================================================
--- /jifty/branches/autoversioning/examples/Example-Todo/etc/config.yml	(original)
+++ jifty/branches/autoversioning/examples/Yada/etc/config.yml	Sun Jul 22 21:13:55 2007
@@ -1,19 +1,22 @@
 --- 
+application:
+  OpenIDSecret: sekrit13
 framework: 
   AdminMode: 1
-  ApplicationClass: Example::Todo
-  ApplicationName: Example-Todo
+  SkipAccessControl: 1
+  ApplicationClass: Yada
+  ApplicationName: Yada
   ApplicationUUID: 80DF397A-D999-11DB-B80A-9318EBB6763A
   Database: 
     CheckSchema: 1
-    Database: example_todo
+    Database: yada
     Driver: SQLite
     Host: localhost
     Password: ''
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
     Version: 0.0.1
-  DevelMode: 1
+  DevelMode: 0
   L10N: 
     PoDir: share/po
   LogLevel: INFO
@@ -21,31 +24,21 @@
   MailerArgs: []
 
   Plugins: 
-    - 
-      SkeletonApp: {}
-
-    - 
-      REST: {}
-
-    - 
-      Halo: {}
-
-    - 
-      ErrorTemplates: {}
-
-    - 
-      OnlineDocs: {}
-
-    - 
-      CompressedCSSandJS: {}
-
-    - 
-      AdminUI: {}
+    - SkeletonApp: {}
+    - REST: {}
+    - ErrorTemplates: {}
+    - OnlineDocs: {}
+    - CompressedCSSandJS: {}
+    - AdminUI: {}
+    - LetMe: {}
+    - User: {}
+    - Authentication::Password: {}
+    - OpenID: {}
 
   PubSub: 
     Backend: Memcached
     Enable: ~
-  TemplateClass: Example::Todo::View
+  TemplateClass: Yada::View
   Web: 
     BaseURL: http://localhost
     DataDir: var/mason

Modified: jifty/branches/autoversioning/examples/Yada/inc/Module/Install.pm
==============================================================================
--- /jifty/branches/autoversioning/examples/Example-Todo/inc/Module/Install.pm	(original)
+++ jifty/branches/autoversioning/examples/Yada/inc/Module/Install.pm	Sun Jul 22 21:13:55 2007
@@ -28,7 +28,7 @@
     # This is not enforced yet, but will be some time in the next few
     # releases once we can make sure it won't clash with custom
     # Module::Install extensions.
-    $VERSION = '0.64';
+    $VERSION = '0.67';
 }
 
 # Whether or not inc::Module::Install is actually loaded, the
@@ -86,7 +86,7 @@
             # delegate back to parent dirs
             goto &$code unless $cwd eq $pwd;
         }
-        $$sym =~ /([^:]+)$/ or die "Cannot autoload $who - $sym";
+        $$sym =~ /([^:]+)$/ or Carp::confess "Cannot autoload $who - $sym";
         unshift @_, ($self, $1);
         goto &{$self->can('call')} unless uc($1) eq $1;
     };

Modified: jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Base.pm
==============================================================================
--- /jifty/branches/autoversioning/examples/Example-Todo/inc/Module/Install/Base.pm	(original)
+++ jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Base.pm	Sun Jul 22 21:13:55 2007
@@ -1,7 +1,7 @@
 #line 1
 package Module::Install::Base;
 
-$VERSION = '0.64';
+$VERSION = '0.67';
 
 # Suspend handler for "redefined" warnings
 BEGIN {

Added: jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Can.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Can.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,82 @@
+#line 1
+package Module::Install::Can;
+
+use strict;
+use Module::Install::Base;
+use Config ();
+### This adds a 5.005 Perl version dependency.
+### This is a bug and will be fixed.
+use File::Spec ();
+use ExtUtils::MakeMaker ();
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.67';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+# check if we can load some module
+### Upgrade this to not have to load the module if possible
+sub can_use {
+	my ($self, $mod, $ver) = @_;
+	$mod =~ s{::|\\}{/}g;
+	$mod .= '.pm' unless $mod =~ /\.pm$/i;
+
+	my $pkg = $mod;
+	$pkg =~ s{/}{::}g;
+	$pkg =~ s{\.pm$}{}i;
+
+	local $@;
+	eval { require $mod; $pkg->VERSION($ver || 0); 1 };
+}
+
+# check if we can run some command
+sub can_run {
+	my ($self, $cmd) = @_;
+
+	my $_cmd = $cmd;
+	return $_cmd if (-x $_cmd or $_cmd = MM->maybe_command($_cmd));
+
+	for my $dir ((split /$Config::Config{path_sep}/, $ENV{PATH}), '.') {
+		my $abs = File::Spec->catfile($dir, $_[1]);
+		return $abs if (-x $abs or $abs = MM->maybe_command($abs));
+	}
+
+	return;
+}
+
+# can we locate a (the) C compiler
+sub can_cc {
+	my $self   = shift;
+	my @chunks = split(/ /, $Config::Config{cc}) or return;
+
+	# $Config{cc} may contain args; try to find out the program part
+	while (@chunks) {
+		return $self->can_run("@chunks") || (pop(@chunks), next);
+	}
+
+	return;
+}
+
+# Fix Cygwin bug on maybe_command();
+if ( $^O eq 'cygwin' ) {
+	require ExtUtils::MM_Cygwin;
+	require ExtUtils::MM_Win32;
+	if ( ! defined(&ExtUtils::MM_Cygwin::maybe_command) ) {
+		*ExtUtils::MM_Cygwin::maybe_command = sub {
+			my ($self, $file) = @_;
+			if ($file =~ m{^/cygdrive/}i and ExtUtils::MM_Win32->can('maybe_command')) {
+				ExtUtils::MM_Win32->maybe_command($file);
+			} else {
+				ExtUtils::MM_Unix->maybe_command($file);
+			}
+		}
+	}
+}
+
+1;
+
+__END__
+
+#line 157

Added: jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Fetch.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Fetch.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,93 @@
+#line 1
+package Module::Install::Fetch;
+
+use strict;
+use Module::Install::Base;
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.67';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+sub get_file {
+    my ($self, %args) = @_;
+    my ($scheme, $host, $path, $file) = 
+        $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;
+
+    if ( $scheme eq 'http' and ! eval { require LWP::Simple; 1 } ) {
+        $args{url} = $args{ftp_url}
+            or (warn("LWP support unavailable!\n"), return);
+        ($scheme, $host, $path, $file) = 
+            $args{url} =~ m|^(\w+)://([^/]+)(.+)/(.+)| or return;
+    }
+
+    $|++;
+    print "Fetching '$file' from $host... ";
+
+    unless (eval { require Socket; Socket::inet_aton($host) }) {
+        warn "'$host' resolve failed!\n";
+        return;
+    }
+
+    return unless $scheme eq 'ftp' or $scheme eq 'http';
+
+    require Cwd;
+    my $dir = Cwd::getcwd();
+    chdir $args{local_dir} or return if exists $args{local_dir};
+
+    if (eval { require LWP::Simple; 1 }) {
+        LWP::Simple::mirror($args{url}, $file);
+    }
+    elsif (eval { require Net::FTP; 1 }) { eval {
+        # use Net::FTP to get past firewall
+        my $ftp = Net::FTP->new($host, Passive => 1, Timeout => 600);
+        $ftp->login("anonymous", 'anonymous at example.com');
+        $ftp->cwd($path);
+        $ftp->binary;
+        $ftp->get($file) or (warn("$!\n"), return);
+        $ftp->quit;
+    } }
+    elsif (my $ftp = $self->can_run('ftp')) { eval {
+        # no Net::FTP, fallback to ftp.exe
+        require FileHandle;
+        my $fh = FileHandle->new;
+
+        local $SIG{CHLD} = 'IGNORE';
+        unless ($fh->open("|$ftp -n")) {
+            warn "Couldn't open ftp: $!\n";
+            chdir $dir; return;
+        }
+
+        my @dialog = split(/\n/, <<"END_FTP");
+open $host
+user anonymous anonymous\@example.com
+cd $path
+binary
+get $file $file
+quit
+END_FTP
+        foreach (@dialog) { $fh->print("$_\n") }
+        $fh->close;
+    } }
+    else {
+        warn "No working 'ftp' program available!\n";
+        chdir $dir; return;
+    }
+
+    unless (-f $file) {
+        warn "Fetching failed: $@\n";
+        chdir $dir; return;
+    }
+
+    return if exists $args{size} and -s $file != $args{size};
+    system($args{run}) if exists $args{run};
+    unlink($file) if $args{remove};
+
+    print(((!exists $args{check_for} or -e $args{check_for})
+        ? "done!" : "failed! ($!)"), "\n");
+    chdir $dir; return !$?;
+}
+
+1;

Added: jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Makefile.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Makefile.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,237 @@
+#line 1
+package Module::Install::Makefile;
+
+use strict 'vars';
+use Module::Install::Base;
+use ExtUtils::MakeMaker ();
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.67';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+sub Makefile { $_[0] }
+
+my %seen = ();
+
+sub prompt {
+	shift;
+
+	# Infinite loop protection
+	my @c = caller();
+	if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) {
+		die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])";
+	}
+
+	# In automated testing, always use defaults
+	if ( $ENV{AUTOMATED_TESTING} and ! $ENV{PERL_MM_USE_DEFAULT} ) {
+		local $ENV{PERL_MM_USE_DEFAULT} = 1;
+		goto &ExtUtils::MakeMaker::prompt;
+	} else {
+		goto &ExtUtils::MakeMaker::prompt;
+	}
+}
+
+sub makemaker_args {
+	my $self = shift;
+	my $args = ($self->{makemaker_args} ||= {});
+	%$args = ( %$args, @_ ) if @_;
+	$args;
+}
+
+# For mm args that take multiple space-seperated args,
+# append an argument to the current list.
+sub makemaker_append {
+	my $self = sShift;
+	my $name = shift;
+	my $args = $self->makemaker_args;
+	$args->{name} = defined $args->{$name}
+		? join( ' ', $args->{name}, @_ )
+		: join( ' ', @_ );
+}
+
+sub build_subdirs {
+	my $self    = shift;
+	my $subdirs = $self->makemaker_args->{DIR} ||= [];
+	for my $subdir (@_) {
+		push @$subdirs, $subdir;
+	}
+}
+
+sub clean_files {
+	my $self  = shift;
+	my $clean = $self->makemaker_args->{clean} ||= {};
+	%$clean = (
+		%$clean, 
+		FILES => join(' ', grep length, $clean->{FILES}, @_),
+	);
+}
+
+sub realclean_files {
+	my $self  = shift;
+	my $realclean = $self->makemaker_args->{realclean} ||= {};
+	%$realclean = (
+		%$realclean, 
+		FILES => join(' ', grep length, $realclean->{FILES}, @_),
+	);
+}
+
+sub libs {
+	my $self = shift;
+	my $libs = ref $_[0] ? shift : [ shift ];
+	$self->makemaker_args( LIBS => $libs );
+}
+
+sub inc {
+	my $self = shift;
+	$self->makemaker_args( INC => shift );
+}
+
+my %test_dir = ();
+
+sub _wanted_t {
+	/\.t$/ and -f $_ and $test_dir{$File::Find::dir} = 1;
+}
+
+sub tests_recursive {
+	my $self = shift;
+	if ( $self->tests ) {
+		die "tests_recursive will not work if tests are already defined";
+	}
+	my $dir = shift || 't';
+	unless ( -d $dir ) {
+		die "tests_recursive dir '$dir' does not exist";
+	}
+	require File::Find;
+	%test_dir = ();
+	File::Find::find( \&_wanted_t, $dir );
+	$self->tests( join ' ', map { "$_/*.t" } sort keys %test_dir );
+}
+
+sub write {
+	my $self = shift;
+	die "&Makefile->write() takes no arguments\n" if @_;
+
+	my $args = $self->makemaker_args;
+	$args->{DISTNAME} = $self->name;
+	$args->{NAME}     = $self->module_name || $self->name || $self->determine_NAME($args);
+	$args->{VERSION}  = $self->version || $self->determine_VERSION($args);
+	$args->{NAME}     =~ s/-/::/g;
+	if ( $self->tests ) {
+		$args->{test} = { TESTS => $self->tests };
+	}
+	if ($] >= 5.005) {
+		$args->{ABSTRACT} = $self->abstract;
+		$args->{AUTHOR}   = $self->author;
+	}
+	if ( eval($ExtUtils::MakeMaker::VERSION) >= 6.10 ) {
+		$args->{NO_META} = 1;
+	}
+	if ( eval($ExtUtils::MakeMaker::VERSION) > 6.17 and $self->sign ) {
+		$args->{SIGN} = 1;
+	}
+	unless ( $self->is_admin ) {
+		delete $args->{SIGN};
+	}
+
+	# merge both kinds of requires into prereq_pm
+	my $prereq = ($args->{PREREQ_PM} ||= {});
+	%$prereq = ( %$prereq,
+		map { @$_ }
+		map { @$_ }
+		grep $_,
+		($self->build_requires, $self->requires)
+	);
+
+	# merge both kinds of requires into prereq_pm
+	my $subdirs = ($args->{DIR} ||= []);
+	if ($self->bundles) {
+		foreach my $bundle (@{ $self->bundles }) {
+			my ($file, $dir) = @$bundle;
+			push @$subdirs, $dir if -d $dir;
+			delete $prereq->{$file};
+		}
+	}
+
+	if ( my $perl_version = $self->perl_version ) {
+		eval "use $perl_version; 1"
+			or die "ERROR: perl: Version $] is installed, "
+			. "but we need version >= $perl_version";
+	}
+
+	$args->{INSTALLDIRS} = $self->installdirs;
+
+	my %args = map { ( $_ => $args->{$_} ) } grep {defined($args->{$_})} keys %$args;
+
+	my $user_preop = delete $args{dist}->{PREOP};
+	if (my $preop = $self->admin->preop($user_preop)) {
+		$args{dist} = $preop;
+	}
+
+	my $mm = ExtUtils::MakeMaker::WriteMakefile(%args);
+	$self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile');
+}
+
+sub fix_up_makefile {
+	my $self          = shift;
+	my $makefile_name = shift;
+	my $top_class     = ref($self->_top) || '';
+	my $top_version   = $self->_top->VERSION || '';
+
+	my $preamble = $self->preamble 
+		? "# Preamble by $top_class $top_version\n"
+			. $self->preamble
+		: '';
+	my $postamble = "# Postamble by $top_class $top_version\n"
+		. ($self->postamble || '');
+
+	local *MAKEFILE;
+	open MAKEFILE, "< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
+	my $makefile = do { local $/; <MAKEFILE> };
+	close MAKEFILE or die $!;
+
+	$makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /;
+	$makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g;
+	$makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g;
+	$makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m;
+	$makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m;
+
+	# Module::Install will never be used to build the Core Perl
+	# Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks
+	# PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist
+	$makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m;
+	#$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m;
+
+	# Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well.
+	$makefile =~ s/("?)-I\$\(PERL_LIB\)\1//g;
+
+	# XXX - This is currently unused; not sure if it breaks other MM-users
+	# $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg;
+
+	open  MAKEFILE, "> $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
+	print MAKEFILE  "$preamble$makefile$postamble" or die $!;
+	close MAKEFILE  or die $!;
+
+	1;
+}
+
+sub preamble {
+	my ($self, $text) = @_;
+	$self->{preamble} = $text . $self->{preamble} if defined $text;
+	$self->{preamble};
+}
+
+sub postamble {
+	my ($self, $text) = @_;
+	$self->{postamble} ||= $self->admin->postamble;
+	$self->{postamble} .= $text if defined $text;
+	$self->{postamble}
+}
+
+1;
+
+__END__
+
+#line 363

Modified: jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Metadata.pm
==============================================================================
--- /jifty/branches/autoversioning/examples/Example-Todo/inc/Module/Install/Metadata.pm	(original)
+++ jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Metadata.pm	Sun Jul 22 21:13:55 2007
@@ -6,14 +6,14 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.64';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }
 
 my @scalar_keys = qw{
     name module_name abstract author version license
-    distribution_type perl_version tests
+    distribution_type perl_version tests installdirs
 };
 
 my @tuple_keys = qw{
@@ -56,9 +56,23 @@
     };
 }
 
+# configure_requires is currently a null-op
+sub configure_requires { 1 }
+
+# Aliases for build_requires that will have alternative
+# meanings in some future version of META.yml.
+sub test_requires      { shift->build_requires(@_)  }
+sub install_requires   { shift->build_requires(@_)  }
+
+# Aliases for installdirs options
+sub install_as_core    { $_[0]->installdirs('perl')   }
+sub install_as_cpan    { $_[0]->installdirs('site')   }
+sub install_as_site    { $_[0]->installdirs('site')   }
+sub install_as_vendor  { $_[0]->installdirs('vendor') }
+
 sub sign {
     my $self = shift;
-    return $self->{'values'}{'sign'} if defined wantarray and !@_;
+    return $self->{'values'}{'sign'} if defined wantarray and ! @_;
     $self->{'values'}{'sign'} = ( @_ ? $_[0] : 1 );
     return $self;
 }
@@ -279,9 +293,11 @@
 
     if (
         $self->_slurp($file) =~ m/
-        =head \d \s+
-        (?:licen[cs]e|licensing|copyright|legal)\b
-        (.*?)
+        (
+            =head \d \s+
+            (?:licen[cs]e|licensing|copyright|legal)\b
+            .*?
+        )
         (=head\\d.*|=cut.*|)
         \z
     /ixms
@@ -289,19 +305,24 @@
     {
         my $license_text = $1;
         my @phrases      = (
-            'under the same (?:terms|license) as perl itself' => 'perl',
-            'GNU public license'                              => 'gpl',
-            'GNU lesser public license'                       => 'gpl',
-            'BSD license'                                     => 'bsd',
-            'Artistic license'                                => 'artistic',
-            'GPL'                                             => 'gpl',
-            'LGPL'                                            => 'lgpl',
-            'BSD'                                             => 'bsd',
-            'Artistic'                                        => 'artistic',
+            'under the same (?:terms|license) as perl itself' => 'perl',        1,
+            'GNU public license'                              => 'gpl',         1,
+            'GNU lesser public license'                       => 'gpl',         1,
+            'BSD license'                                     => 'bsd',         1,
+            'Artistic license'                                => 'artistic',    1,
+            'GPL'                                             => 'gpl',         1,
+            'LGPL'                                            => 'lgpl',        1,
+            'BSD'                                             => 'bsd',         1,
+            'Artistic'                                        => 'artistic',    1,
+            'MIT'                                             => 'mit',         1,
+            'proprietary'                                     => 'proprietary', 0,
         );
-        while ( my ( $pattern, $license ) = splice( @phrases, 0, 2 ) ) {
+        while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) {
             $pattern =~ s{\s+}{\\s+}g;
             if ( $license_text =~ /\b$pattern\b/i ) {
+                if ( $osi and $license_text =~ /All rights reserved/i ) {
+                        warn "LEGAL WARNING: 'All rights reserved' may invalidate Open Source licenses. Consider removing it.";
+		}
                 $self->license($license);
                 return 1;
             }

Added: jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Win32.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/examples/Yada/inc/Module/Install/Win32.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,65 @@
+#line 1
+package Module::Install::Win32;
+
+use strict;
+use Module::Install::Base;
+
+use vars qw{$VERSION $ISCORE @ISA};
+BEGIN {
+	$VERSION = '0.67';
+	$ISCORE  = 1;
+	@ISA     = qw{Module::Install::Base};
+}
+
+# determine if the user needs nmake, and download it if needed
+sub check_nmake {
+	my $self = shift;
+	$self->load('can_run');
+	$self->load('get_file');
+	
+	require Config;
+	return unless (
+		$^O eq 'MSWin32'                     and
+		$Config::Config{make}                and
+		$Config::Config{make} =~ /^nmake\b/i and
+		! $self->can_run('nmake')
+	);
+
+	print "The required 'nmake' executable not found, fetching it...\n";
+
+	require File::Basename;
+	my $rv = $self->get_file(
+		url       => 'http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe',
+		ftp_url   => 'ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe',
+		local_dir => File::Basename::dirname($^X),
+		size      => 51928,
+		run       => 'Nmake15.exe /o > nul',
+		check_for => 'Nmake.exe',
+		remove    => 1,
+	);
+
+	if (!$rv) {
+        die <<'END_MESSAGE';
+
+-------------------------------------------------------------------------------
+
+Since you are using Microsoft Windows, you will need the 'nmake' utility
+before installation. It's available at:
+
+  http://download.microsoft.com/download/vc15/Patch/1.52/W95/EN-US/Nmake15.exe
+      or
+  ftp://ftp.microsoft.com/Softlib/MSLFILES/Nmake15.exe
+
+Please download the file manually, save it to a directory in %PATH% (e.g.
+C:\WINDOWS\COMMAND\), then launch the MS-DOS command line shell, "cd" to
+that directory, and run "Nmake15.exe" from there; that will create the
+'nmake.exe' file needed by this module.
+
+You may then resume the installation process described in README.
+
+-------------------------------------------------------------------------------
+END_MESSAGE
+	}
+}
+
+1;

Modified: jifty/branches/autoversioning/examples/Yada/inc/Module/Install/WriteAll.pm
==============================================================================
--- /jifty/branches/autoversioning/examples/Example-Todo/inc/Module/Install/WriteAll.pm	(original)
+++ jifty/branches/autoversioning/examples/Yada/inc/Module/Install/WriteAll.pm	Sun Jul 22 21:13:55 2007
@@ -6,7 +6,7 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.64';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }

Added: jifty/branches/autoversioning/examples/Yada/lib/Yada/Model/Todo.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/examples/Yada/lib/Yada/Model/Todo.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,17 @@
+use strict;
+use warnings;
+
+package Yada::Model::Todo;
+use Jifty::DBI::Schema;
+
+use Yada::Record schema {
+
+    column done => type is 'bool';
+    column description => type is 'text';
+
+};
+
+# Your model-specific methods go here.
+
+1;
+

Added: jifty/branches/autoversioning/examples/Yada/lib/Yada/Model/User.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/examples/Yada/lib/Yada/Model/User.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,11 @@
+package Yada::Model::User;
+#use base 'Example::Todo::Record';
+use Jifty::DBI::Schema;
+
+use Yada::Record schema {};
+
+use Jifty::Plugin::User::Mixin::Model::User;
+use Jifty::Plugin::Authentication::Password::Mixin::Model::User;
+use Jifty::Plugin::OpenID::Mixin::Model::User;
+
+1;

Added: jifty/branches/autoversioning/examples/Yada/lib/Yada/View.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/examples/Yada/lib/Yada/View.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,18 @@
+package Yada::View;
+use Jifty::View::Declare -base;
+
+template 'index.html' => page {
+    my $self = shift;
+    title { _('Yada!') };
+
+    form {
+	render_region(name => 'list', path => '/todo/list');
+    }
+};
+
+use Jifty::View::Declare::CRUD;
+for (qw/todo/) {
+    Jifty::View::Declare::CRUD->mount_view($_);
+}
+
+1;

Added: jifty/branches/autoversioning/examples/Yada/lib/Yada/View/Todo.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/examples/Yada/lib/Yada/View/Todo.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,6 @@
+package Yada::View::Todo;
+use strict;
+use Jifty::View::Declare -base;
+use base 'Jifty::View::Declare::CRUD';
+
+1;

Modified: jifty/branches/autoversioning/examples/Yada/t/00-model-Todo.t
==============================================================================
--- /jifty/branches/autoversioning/examples/Example-Todo/t/00-model-Todo.t	(original)
+++ jifty/branches/autoversioning/examples/Yada/t/00-model-Todo.t	Sun Jul 22 21:13:55 2007
@@ -11,14 +11,14 @@
 use Jifty::Test tests => 11;
 
 # Make sure we can load the model
-use_ok('Example::Todo::Model::Todo');
+use_ok('Yada::Model::Todo');
 
 # Grab a system user
-my $system_user = Example::Todo::CurrentUser->superuser;
+my $system_user = Yada::CurrentUser->superuser;
 ok($system_user, "Found a system user");
 
 # Try testing a create
-my $o = Example::Todo::Model::Todo->new(current_user => $system_user);
+my $o = Yada::Model::Todo->new(current_user => $system_user);
 my ($id) = $o->create();
 ok($id, "Todo create returned success");
 ok($o->id, "New Todo has valid id set");
@@ -30,7 +30,7 @@
 isnt($o->id, $id, "And it is different from the previous one");
 
 # Searches in general
-my $collection =  Example::Todo::Model::TodoCollection->new(current_user => $system_user);
+my $collection =  Yada::Model::TodoCollection->new(current_user => $system_user);
 $collection->unlimit;
 is($collection->count, 2, "Finds two records");
 

Modified: jifty/branches/autoversioning/inc/Module/Install.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install.pm	Sun Jul 22 21:13:55 2007
@@ -28,7 +28,7 @@
     # This is not enforced yet, but will be some time in the next few
     # releases once we can make sure it won't clash with custom
     # Module::Install extensions.
-    $VERSION = '0.65';
+    $VERSION = '0.67';
 }
 
 # Whether or not inc::Module::Install is actually loaded, the

Modified: jifty/branches/autoversioning/inc/Module/Install/AutoInstall.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install/AutoInstall.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install/AutoInstall.pm	Sun Jul 22 21:13:55 2007
@@ -6,7 +6,7 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.65';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }

Modified: jifty/branches/autoversioning/inc/Module/Install/Base.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install/Base.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install/Base.pm	Sun Jul 22 21:13:55 2007
@@ -1,7 +1,7 @@
 #line 1
 package Module::Install::Base;
 
-$VERSION = '0.65';
+$VERSION = '0.67';
 
 # Suspend handler for "redefined" warnings
 BEGIN {

Modified: jifty/branches/autoversioning/inc/Module/Install/Can.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install/Can.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install/Can.pm	Sun Jul 22 21:13:55 2007
@@ -11,7 +11,7 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.65';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }

Modified: jifty/branches/autoversioning/inc/Module/Install/Fetch.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install/Fetch.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install/Fetch.pm	Sun Jul 22 21:13:55 2007
@@ -6,7 +6,7 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.65';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }

Modified: jifty/branches/autoversioning/inc/Module/Install/Include.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install/Include.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install/Include.pm	Sun Jul 22 21:13:55 2007
@@ -6,7 +6,7 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.65';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }

Modified: jifty/branches/autoversioning/inc/Module/Install/Makefile.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install/Makefile.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install/Makefile.pm	Sun Jul 22 21:13:55 2007
@@ -7,7 +7,7 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.65';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }
@@ -17,196 +17,221 @@
 my %seen = ();
 
 sub prompt {
-    shift;
+	shift;
 
-    # Infinite loop protection
-    my @c = caller();
-    if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) {
-        die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])";
-    }
-
-    # In automated testing, always use defaults
-    if ( $ENV{AUTOMATED_TESTING} and ! $ENV{PERL_MM_USE_DEFAULT} ) {
-        local $ENV{PERL_MM_USE_DEFAULT} = 1;
-        goto &ExtUtils::MakeMaker::prompt;
-    } else {
-        goto &ExtUtils::MakeMaker::prompt;
-    }
+	# Infinite loop protection
+	my @c = caller();
+	if ( ++$seen{"$c[1]|$c[2]|$_[0]"} > 3 ) {
+		die "Caught an potential prompt infinite loop ($c[1]|$c[2]|$_[0])";
+	}
+
+	# In automated testing, always use defaults
+	if ( $ENV{AUTOMATED_TESTING} and ! $ENV{PERL_MM_USE_DEFAULT} ) {
+		local $ENV{PERL_MM_USE_DEFAULT} = 1;
+		goto &ExtUtils::MakeMaker::prompt;
+	} else {
+		goto &ExtUtils::MakeMaker::prompt;
+	}
 }
 
 sub makemaker_args {
-    my $self = shift;
-    my $args = ($self->{makemaker_args} ||= {});
-    %$args = ( %$args, @_ ) if @_;
-    $args;
+	my $self = shift;
+	my $args = ($self->{makemaker_args} ||= {});
+	%$args = ( %$args, @_ ) if @_;
+	$args;
 }
 
 # For mm args that take multiple space-seperated args,
 # append an argument to the current list.
 sub makemaker_append {
-    my $self = shift;
-    my $name = shift;
-    my $args = $self->makemaker_args;
-    $args->{name} = defined $args->{$name}
-    	? join( ' ', $args->{name}, @_ )
-    	: join( ' ', @_ );
+	my $self = sShift;
+	my $name = shift;
+	my $args = $self->makemaker_args;
+	$args->{name} = defined $args->{$name}
+		? join( ' ', $args->{name}, @_ )
+		: join( ' ', @_ );
 }
 
 sub build_subdirs {
-    my $self    = shift;
-    my $subdirs = $self->makemaker_args->{DIR} ||= [];
-    for my $subdir (@_) {
-        push @$subdirs, $subdir;
-    }
+	my $self    = shift;
+	my $subdirs = $self->makemaker_args->{DIR} ||= [];
+	for my $subdir (@_) {
+		push @$subdirs, $subdir;
+	}
 }
 
 sub clean_files {
-    my $self  = shift;
-    my $clean = $self->makemaker_args->{clean} ||= {};
-    %$clean = (
-        %$clean, 
-        FILES => join(' ', grep length, $clean->{FILES}, @_),
-    );
+	my $self  = shift;
+	my $clean = $self->makemaker_args->{clean} ||= {};
+	%$clean = (
+		%$clean, 
+		FILES => join(' ', grep length, $clean->{FILES}, @_),
+	);
 }
 
 sub realclean_files {
-    my $self  = shift;
-    my $realclean = $self->makemaker_args->{realclean} ||= {};
-    %$realclean = (
-        %$realclean, 
-        FILES => join(' ', grep length, $realclean->{FILES}, @_),
-    );
+	my $self  = shift;
+	my $realclean = $self->makemaker_args->{realclean} ||= {};
+	%$realclean = (
+		%$realclean, 
+		FILES => join(' ', grep length, $realclean->{FILES}, @_),
+	);
 }
 
 sub libs {
-    my $self = shift;
-    my $libs = ref $_[0] ? shift : [ shift ];
-    $self->makemaker_args( LIBS => $libs );
+	my $self = shift;
+	my $libs = ref $_[0] ? shift : [ shift ];
+	$self->makemaker_args( LIBS => $libs );
 }
 
 sub inc {
-    my $self = shift;
-    $self->makemaker_args( INC => shift );
+	my $self = shift;
+	$self->makemaker_args( INC => shift );
+}
+
+my %test_dir = ();
+
+sub _wanted_t {
+	/\.t$/ and -f $_ and $test_dir{$File::Find::dir} = 1;
+}
+
+sub tests_recursive {
+	my $self = shift;
+	if ( $self->tests ) {
+		die "tests_recursive will not work if tests are already defined";
+	}
+	my $dir = shift || 't';
+	unless ( -d $dir ) {
+		die "tests_recursive dir '$dir' does not exist";
+	}
+	require File::Find;
+	%test_dir = ();
+	File::Find::find( \&_wanted_t, $dir );
+	$self->tests( join ' ', map { "$_/*.t" } sort keys %test_dir );
 }
 
 sub write {
-    my $self = shift;
-    die "&Makefile->write() takes no arguments\n" if @_;
+	my $self = shift;
+	die "&Makefile->write() takes no arguments\n" if @_;
 
-    my $args = $self->makemaker_args;
-    $args->{DISTNAME} = $self->name;
-    $args->{NAME}     = $self->module_name || $self->name || $self->determine_NAME($args);
-    $args->{VERSION}  = $self->version || $self->determine_VERSION($args);
-    $args->{NAME}     =~ s/-/::/g;
-    if ( $self->tests ) {
-        $args->{test} = { TESTS => $self->tests };
-    }
-    if ($] >= 5.005) {
-        $args->{ABSTRACT} = $self->abstract;
-        $args->{AUTHOR}   = $self->author;
-    }
-    if ( eval($ExtUtils::MakeMaker::VERSION) >= 6.10 ) {
-        $args->{NO_META} = 1;
-    }
-    if ( eval($ExtUtils::MakeMaker::VERSION) > 6.17 and $self->sign ) {
-        $args->{SIGN} = 1;
-    }
-    unless ( $self->is_admin ) {
-        delete $args->{SIGN};
-    }
-
-    # merge both kinds of requires into prereq_pm
-    my $prereq = ($args->{PREREQ_PM} ||= {});
-    %$prereq = ( %$prereq, map { @$_ } map { @$_ } grep $_,
-                 ($self->build_requires, $self->requires) );
-
-    # merge both kinds of requires into prereq_pm
-    my $subdirs = ($args->{DIR} ||= []);
-    if ($self->bundles) {
-        foreach my $bundle (@{ $self->bundles }) {
-            my ($file, $dir) = @$bundle;
-            push @$subdirs, $dir if -d $dir;
-            delete $prereq->{$file};
-        }
-    }
-
-    if ( my $perl_version = $self->perl_version ) {
-        eval "use $perl_version; 1"
-            or die "ERROR: perl: Version $] is installed, "
-                . "but we need version >= $perl_version";
-    }
-
-    $args->{INSTALLDIRS} = $self->installdirs;
-
-    my %args = map { ( $_ => $args->{$_} ) } grep {defined($args->{$_})} keys %$args;
-
-    my $user_preop = delete $args{dist}->{PREOP};
-    if (my $preop = $self->admin->preop($user_preop)) {
-        $args{dist} = $preop;
-    }
+	my $args = $self->makemaker_args;
+	$args->{DISTNAME} = $self->name;
+	$args->{NAME}     = $self->module_name || $self->name || $self->determine_NAME($args);
+	$args->{VERSION}  = $self->version || $self->determine_VERSION($args);
+	$args->{NAME}     =~ s/-/::/g;
+	if ( $self->tests ) {
+		$args->{test} = { TESTS => $self->tests };
+	}
+	if ($] >= 5.005) {
+		$args->{ABSTRACT} = $self->abstract;
+		$args->{AUTHOR}   = $self->author;
+	}
+	if ( eval($ExtUtils::MakeMaker::VERSION) >= 6.10 ) {
+		$args->{NO_META} = 1;
+	}
+	if ( eval($ExtUtils::MakeMaker::VERSION) > 6.17 and $self->sign ) {
+		$args->{SIGN} = 1;
+	}
+	unless ( $self->is_admin ) {
+		delete $args->{SIGN};
+	}
+
+	# merge both kinds of requires into prereq_pm
+	my $prereq = ($args->{PREREQ_PM} ||= {});
+	%$prereq = ( %$prereq,
+		map { @$_ }
+		map { @$_ }
+		grep $_,
+		($self->build_requires, $self->requires)
+	);
+
+	# merge both kinds of requires into prereq_pm
+	my $subdirs = ($args->{DIR} ||= []);
+	if ($self->bundles) {
+		foreach my $bundle (@{ $self->bundles }) {
+			my ($file, $dir) = @$bundle;
+			push @$subdirs, $dir if -d $dir;
+			delete $prereq->{$file};
+		}
+	}
+
+	if ( my $perl_version = $self->perl_version ) {
+		eval "use $perl_version; 1"
+			or die "ERROR: perl: Version $] is installed, "
+			. "but we need version >= $perl_version";
+	}
+
+	$args->{INSTALLDIRS} = $self->installdirs;
+
+	my %args = map { ( $_ => $args->{$_} ) } grep {defined($args->{$_})} keys %$args;
+
+	my $user_preop = delete $args{dist}->{PREOP};
+	if (my $preop = $self->admin->preop($user_preop)) {
+		$args{dist} = $preop;
+	}
 
-    my $mm = ExtUtils::MakeMaker::WriteMakefile(%args);
-    $self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile');
+	my $mm = ExtUtils::MakeMaker::WriteMakefile(%args);
+	$self->fix_up_makefile($mm->{FIRST_MAKEFILE} || 'Makefile');
 }
 
 sub fix_up_makefile {
-    my $self          = shift;
-    my $makefile_name = shift;
-    my $top_class     = ref($self->_top) || '';
-    my $top_version   = $self->_top->VERSION || '';
-
-    my $preamble = $self->preamble 
-        ? "# Preamble by $top_class $top_version\n"
-            . $self->preamble
-        : '';
-    my $postamble = "# Postamble by $top_class $top_version\n"
-        . ($self->postamble || '');
-
-    local *MAKEFILE;
-    open MAKEFILE, "< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
-    my $makefile = do { local $/; <MAKEFILE> };
-    close MAKEFILE or die $!;
-
-    $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /;
-    $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g;
-    $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g;
-    $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m;
-    $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m;
-
-    # Module::Install will never be used to build the Core Perl
-    # Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks
-    # PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist
-    $makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m;
-    #$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m;
-
-    # Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well.
-    $makefile =~ s/("?)-I\$\(PERL_LIB\)\1//g;
-
-    # XXX - This is currently unused; not sure if it breaks other MM-users
-    # $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg;
-
-    open  MAKEFILE, "> $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
-    print MAKEFILE  "$preamble$makefile$postamble" or die $!;
-    close MAKEFILE  or die $!;
+	my $self          = shift;
+	my $makefile_name = shift;
+	my $top_class     = ref($self->_top) || '';
+	my $top_version   = $self->_top->VERSION || '';
+
+	my $preamble = $self->preamble 
+		? "# Preamble by $top_class $top_version\n"
+			. $self->preamble
+		: '';
+	my $postamble = "# Postamble by $top_class $top_version\n"
+		. ($self->postamble || '');
+
+	local *MAKEFILE;
+	open MAKEFILE, "< $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
+	my $makefile = do { local $/; <MAKEFILE> };
+	close MAKEFILE or die $!;
+
+	$makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /;
+	$makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g;
+	$makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g;
+	$makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m;
+	$makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m;
+
+	# Module::Install will never be used to build the Core Perl
+	# Sometimes PERL_LIB and PERL_ARCHLIB get written anyway, which breaks
+	# PREFIX/PERL5LIB, and thus, install_share. Blank them if they exist
+	$makefile =~ s/^PERL_LIB = .+/PERL_LIB =/m;
+	#$makefile =~ s/^PERL_ARCHLIB = .+/PERL_ARCHLIB =/m;
+
+	# Perl 5.005 mentions PERL_LIB explicitly, so we have to remove that as well.
+	$makefile =~ s/("?)-I\$\(PERL_LIB\)\1//g;
+
+	# XXX - This is currently unused; not sure if it breaks other MM-users
+	# $makefile =~ s/^pm_to_blib\s+:\s+/pm_to_blib :: /mg;
+
+	open  MAKEFILE, "> $makefile_name" or die "fix_up_makefile: Couldn't open $makefile_name: $!";
+	print MAKEFILE  "$preamble$makefile$postamble" or die $!;
+	close MAKEFILE  or die $!;
 
-    1;
+	1;
 }
 
 sub preamble {
-    my ($self, $text) = @_;
-    $self->{preamble} = $text . $self->{preamble} if defined $text;
-    $self->{preamble};
+	my ($self, $text) = @_;
+	$self->{preamble} = $text . $self->{preamble} if defined $text;
+	$self->{preamble};
 }
 
 sub postamble {
-    my ($self, $text) = @_;
-    $self->{postamble} ||= $self->admin->postamble;
-    $self->{postamble} .= $text if defined $text;
-    $self->{postamble}
+	my ($self, $text) = @_;
+	$self->{postamble} ||= $self->admin->postamble;
+	$self->{postamble} .= $text if defined $text;
+	$self->{postamble}
 }
 
 1;
 
 __END__
 
-#line 338
+#line 363

Modified: jifty/branches/autoversioning/inc/Module/Install/Metadata.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install/Metadata.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install/Metadata.pm	Sun Jul 22 21:13:55 2007
@@ -6,7 +6,7 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.65';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }
@@ -56,14 +56,23 @@
     };
 }
 
-sub install_as_core   { $_[0]->installdirs('perl')   }
-sub install_as_cpan   { $_[0]->installdirs('site')   }
-sub install_as_site   { $_[0]->installdirs('site')   }
-sub install_as_vendor { $_[0]->installdirs('vendor') }
+# configure_requires is currently a null-op
+sub configure_requires { 1 }
+
+# Aliases for build_requires that will have alternative
+# meanings in some future version of META.yml.
+sub test_requires      { shift->build_requires(@_)  }
+sub install_requires   { shift->build_requires(@_)  }
+
+# Aliases for installdirs options
+sub install_as_core    { $_[0]->installdirs('perl')   }
+sub install_as_cpan    { $_[0]->installdirs('site')   }
+sub install_as_site    { $_[0]->installdirs('site')   }
+sub install_as_vendor  { $_[0]->installdirs('vendor') }
 
 sub sign {
     my $self = shift;
-    return $self->{'values'}{'sign'} if defined wantarray and !@_;
+    return $self->{'values'}{'sign'} if defined wantarray and ! @_;
     $self->{'values'}{'sign'} = ( @_ ? $_[0] : 1 );
     return $self;
 }
@@ -296,20 +305,24 @@
     {
         my $license_text = $1;
         my @phrases      = (
-            'under the same (?:terms|license) as perl itself' => 'perl',
-            'GNU public license'                              => 'gpl',
-            'GNU lesser public license'                       => 'gpl',
-            'BSD license'                                     => 'bsd',
-            'Artistic license'                                => 'artistic',
-            'GPL'                                             => 'gpl',
-            'LGPL'                                            => 'lgpl',
-            'BSD'                                             => 'bsd',
-            'Artistic'                                        => 'artistic',
-            'MIT'                                             => 'MIT',
+            'under the same (?:terms|license) as perl itself' => 'perl',        1,
+            'GNU public license'                              => 'gpl',         1,
+            'GNU lesser public license'                       => 'gpl',         1,
+            'BSD license'                                     => 'bsd',         1,
+            'Artistic license'                                => 'artistic',    1,
+            'GPL'                                             => 'gpl',         1,
+            'LGPL'                                            => 'lgpl',        1,
+            'BSD'                                             => 'bsd',         1,
+            'Artistic'                                        => 'artistic',    1,
+            'MIT'                                             => 'mit',         1,
+            'proprietary'                                     => 'proprietary', 0,
         );
-        while ( my ( $pattern, $license ) = splice( @phrases, 0, 2 ) ) {
+        while ( my ($pattern, $license, $osi) = splice(@phrases, 0, 3) ) {
             $pattern =~ s{\s+}{\\s+}g;
             if ( $license_text =~ /\b$pattern\b/i ) {
+                if ( $osi and $license_text =~ /All rights reserved/i ) {
+                        warn "LEGAL WARNING: 'All rights reserved' may invalidate Open Source licenses. Consider removing it.";
+		}
                 $self->license($license);
                 return 1;
             }

Modified: jifty/branches/autoversioning/inc/Module/Install/Scripts.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install/Scripts.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install/Scripts.pm	Sun Jul 22 21:13:55 2007
@@ -7,7 +7,7 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.65';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }

Modified: jifty/branches/autoversioning/inc/Module/Install/Share.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install/Share.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install/Share.pm	Sun Jul 22 21:13:55 2007
@@ -6,7 +6,7 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.65';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }

Modified: jifty/branches/autoversioning/inc/Module/Install/Win32.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install/Win32.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install/Win32.pm	Sun Jul 22 21:13:55 2007
@@ -6,7 +6,7 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.65';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }

Modified: jifty/branches/autoversioning/inc/Module/Install/WriteAll.pm
==============================================================================
--- jifty/branches/autoversioning/inc/Module/Install/WriteAll.pm	(original)
+++ jifty/branches/autoversioning/inc/Module/Install/WriteAll.pm	Sun Jul 22 21:13:55 2007
@@ -6,7 +6,7 @@
 
 use vars qw{$VERSION $ISCORE @ISA};
 BEGIN {
-	$VERSION = '0.65';
+	$VERSION = '0.67';
 	$ISCORE  = 1;
 	@ISA     = qw{Module::Install::Base};
 }

Modified: jifty/branches/autoversioning/lib/Jifty.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty.pm	Sun Jul 22 21:13:55 2007
@@ -167,9 +167,19 @@
     # Set up plugins
     my @plugins;
     my @plugins_to_load = @{Jifty->config->framework('Plugins')};
+    my $app_plugin = Jifty->app_class('Plugin');
     for (my $i = 0; my $plugin = $plugins_to_load[$i]; $i++) {
-        my $class = "Jifty::Plugin::".(keys %{$plugin})[0];
-        my %options = %{ $plugin->{(keys %{$plugin})[0]} };
+        my $plugin_name = (keys %{$plugin})[0];
+        my $class;
+        if ($plugin_name =~ /^(?:Jifty::Plugin|$app_plugin)::/) {
+            # app-specific plugins use fully qualified names, Jifty plugins may
+            $class = $plugin_name; 
+        }
+        # otherwise, assume it's a short name, qualify it
+        else {
+            $class = "Jifty::Plugin::".$plugin_name;
+        }
+        my %options = %{ $plugin->{ $plugin_name } };
         Jifty::Util->require($class);
         Jifty::ClassLoader->new(base => $class)->require;
         my $plugin_obj = $class->new(%options);
@@ -373,6 +383,18 @@
     return @PLUGINS;
 }
 
+=head2 find_plugin
+
+Find plugins by name.
+
+=cut
+
+sub find_plugin {
+    my $self = shift;
+    my $name = shift;
+    return grep { $_->isa($name) } Jifty->plugins;
+}
+
 =head2 class_loader
 
 An accessor for the L<Jifty::ClassLoader> object that stores the loaded

Modified: jifty/branches/autoversioning/lib/Jifty/API.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/API.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/API.pm	Sun Jul 22 21:13:55 2007
@@ -24,7 +24,7 @@
  my @actions = Jifty->api->actions;
 
  # Check to see if an action is allowed
- if (Jifty->api->is_allow('TrueFooBar')) {
+ if (Jifty->api->is_allowed('TrueFooBar')) {
      # do something...
  }
 
@@ -85,13 +85,13 @@
     my $self   = shift;
     my $action = shift;
 
-    my $base_path = Jifty->app_class("Action");
+    my $base_path = Jifty->app_class;
 
     return $action
-        if $action =~ /^Jifty::/
-        or $action =~ /^\Q$base_path\E/;
+        if ($action =~ /^Jifty::/
+        or $action =~ /^\Q$base_path\E::/);
 
-    return $base_path . "::" . $action;
+    return $base_path . "::Action::" . $action;
 }
 
 =head2 reset
@@ -204,7 +204,7 @@
 
 =head2 is_allowed CLASS
 
-Returns false if the I<CLASS> name (which is fully qualified if it is
+Returns true if the I<CLASS> name (which is fully qualified if it is
 not already) is allowed to be executed.  See L</restrict> above for
 the rules that the class name must pass.
 

Modified: jifty/branches/autoversioning/lib/Jifty/Action.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Action.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Action.pm	Sun Jul 22 21:13:55 2007
@@ -36,7 +36,7 @@
 See also L<Jifty::Action::Record> for data-oriented actions, 
 L<Jifty::Result> for how to return values from actions.
 
-See L<Jifty::Param::Schema> for more details on the declarative 
+See L<Jifty::Param::Schema> for more details on the declarative
 syntax.
 
 See L<Jifty::Manual::Actions> for examples of using actions.
@@ -57,7 +57,8 @@
 
 B<Do not call this directly>; always go through C<< Jifty->web->new_action >>! 
 
-This method constructs a new action. Subclasses who need do custom initialization should start with:
+This method constructs a new action. Subclasses who need do custom
+initialization should start with:
 
     my $class = shift;
     my $self = $class->SUPER::new(@_)
@@ -81,29 +82,20 @@
 =item arguments
 
 A hash reference of default values for the
-L<arguments|Jifty::Manual::Glossary/argument> of the action.  Defaults to
-none.
+L<arguments|Jifty::Manual::Glossary/argument> of the action.  Defaults
+to none.
 
 =item sticky_on_failure
 
 A boolean value that determines if the form fields are
-L<sticky|Jifty::Manual::Glossary/sticky> when the action fails.  Defaults to
-true.
+L<sticky|Jifty::Manual::Glossary/sticky> when the action fails.
+Defaults to true.
 
 =item sticky_on_success
 
 A boolean value that determines if the form fields are
-L<sticky|Jifty::Manual::Glossary/sticky> when the action succeeds.  Defaults
-to false.
-
-=begin private
-
-=item request_arguments
-
-A hashref of arguments passed in as part of the
-L<Jifty::Request>. Internal use only.
-
-=end private
+L<sticky|Jifty::Manual::Glossary/sticky> when the action succeeds.
+Defaults to false.
 
 =back
 
@@ -127,13 +119,16 @@
         $self->_get_current_user();
     }
 
-    if ($args{'moniker'}) {
-        $self->moniker($args{'moniker'});
-    } else {
-        $self->moniker($self->_generate_moniker);
-    }
+    $self->moniker($args{'moniker'} || $self->_generate_moniker);
     $self->order($args{'order'});
 
+    my $action_in_request = Jifty->web->request->action( $self->moniker );
+    # Fields explicitly passed to new_action take precedence over those passed
+    # from the request; we read from the request to implement "sticky fields".
+    if ( $action_in_request and $action_in_request->arguments ) {
+        $args{'request_arguments'} = $action_in_request->arguments;
+    }
+
     $self->argument_values( { %{ $args{'request_arguments' } }, %{ $args{'arguments'} } } );
 
     # Keep track of whether arguments came from the request, or were
@@ -153,11 +148,12 @@
 
 =head2 _generate_moniker 
 
-Construct a moniker for a new (or soon-to-be-constructed) action that did not have
-an explicit moniker specified.  The algorithm is simple: We snapshot the call stack,
-prefix it with the action class, and then append it with an per-request autoincrement
-counter in case the same class/stack is encountered twice, which can happen if the
-programmer placed a C<new_action> call inside a loop.
+Construct a moniker for a new (or soon-to-be-constructed) action that
+did not have an explicit moniker specified.  The algorithm is simple:
+We snapshot the call stack, prefix it with the action class, and then
+append it with an per-request autoincrement counter in case the same
+class/stack is encountered twice, which can happen if the programmer
+placed a C<new_action> call inside a loop.
 
 Monikers generated this way are guaranteed to work across requests.
 
@@ -1105,6 +1101,27 @@
 
 }
 
+=head2 deny REASON
+
+When access to an action is denied by L<Jifty::API::is_allowed> 
+the request handler calls this with a message.
+
+This should mark the action as failed and store the message
+but may also want to do other things (such as providing a nicer message
+or logging somewhere other than the jifty logs)
+
+=cut
+
+sub deny {
+    my $self = shift;
+    my $message = shift||'';
+
+    $self->result->failure(1);
+    $self->result->message($message);
+
+    return;
+}
+
 =head2 autogenerated
 
 Autogenerated Actions will always return true when this method is called. 
@@ -1114,9 +1131,13 @@
 
 =head2 Canonicalization
 
-If you wish to have the data in a field normalized into a particular format (such as changing a date into YYYY-MM-DD format, adding commas to numbers, capitalizing words, or whatever you need) you can do so using a canonicalizer. 
+If you wish to have the data in a field normalized into a particular
+format (such as changing a date into YYYY-MM-DD format, adding commas
+to numbers, capitalizing words, or whatever you need) you can do so
+using a canonicalizer.
 
-This is just a method titled C<canonicalize_FIELD> where C<FIELD> is the name of the field be normalized. Here is an example:
+This is just a method titled C<canonicalize_FIELD> where C<FIELD> is
+the name of the field be normalized. Here is an example:
 
   sub canonicalize_foo {
       my ($self, $value) = @_;
@@ -1127,21 +1148,28 @@
       return $normal_form;
   }
 
-In this case, all values in the "foo" field will be changed into lower case.
+In this case, all values in the "foo" field will be changed into lower
+case.
 
-While doing this you might also want to call the L</canonicalization_note> to inform the client of the modification:
+While doing this you might also want to call the
+L</canonicalization_note> to inform the client of the modification:
 
   my $normal_form = lc($value);
   $self->canonicalization_note( 
       foo => _('Foo values are always in lowercase.'));
 
-If the "foo" field has "ajax canoncalizes" set in the action schema, then this process will be performed automatically as the form is being filled without reloading the page.
+If the "foo" field has "ajax canoncalizes" set in the action schema,
+then this process will be performed automatically as the form is being
+filled without reloading the page.
 
 =head2 Validation
 
-If a value must follow a certain format, you can provide a validation method for fields to make sure that no value enters the database until it is in a valid form.
+If a value must follow a certain format, you can provide a validation
+method for fields to make sure that no value enters the database until
+it is in a valid form.
 
-A validation method is one named C<validate_FIELD> where C<FIELD> is the name of the field being checked. Here is an example:
+A validation method is one named C<validate_FIELD> where C<FIELD> is
+the name of the field being checked. Here is an example:
 
   sub validate_foo {
       my ($self, $value) = @_;
@@ -1161,15 +1189,26 @@
       return 1;
   }
 
-Here the "foo" field should not contain uppercase letters and must not contain the characters '-', '*', '+', or '?'. You can use L</validation_error> and L</validation_warning> to return the results of your validation to the user or simply return 1 to indicate a valid value.
+Here the "foo" field should not contain uppercase letters and must not
+contain the characters '-', '*', '+', or '?'. You can use
+L</validation_error> and L</validation_warning> to return the results
+of your validation to the user or simply return 1 to indicate a valid
+value.
 
-If you just have a list of valid values, you may want to use the C<valid_values> schema parameter to perform this task instead.
+If you just have a list of valid values, you may want to use the
+C<valid_values> schema parameter to perform this task instead.
 
 =head2 Autocompletion
 
-Autocompletion provides a way of suggesting choices to the client based upon partial data entry. This doesn't necessarily force the client to use one of the choices given but gives hints in an application specific way.
-
-To create an autocompletion field, you implement a method named C<autocomplete_FIELD> where C<FIELD> is the field to autocomplete. This is generally done with fields rendered as 'Text'. Here is an example:
+Autocompletion provides a way of suggesting choices to the client
+based upon partial data entry. This doesn't necessarily force the
+client to use one of the choices given but gives hints in an
+application specific way.
+
+To create an autocompletion field, you implement a method named
+C<autocomplete_FIELD> where C<FIELD> is the field to
+autocomplete. This is generally done with fields rendered as
+'Text'. Here is an example:
 
   sub autocomplete_foo {
       my ($self, $value) = @_;
@@ -1188,16 +1227,25 @@
       return map { $_->name } @{ $foos->items_array_ref };
   }
 
-In this example, the "foo" field is autocompleted from names matched from the C<MyApp::Model::Foo> table. The match, in this case, matches any substring found in the database. I could have matched any item that starts with the string, ends with the string, matches other fields than the one returned, etc. It's up to you to decide.
-
-Note also that I have untainted the value coming in to make sure a malicious user doesn't get anyway. You should always perform a check like this when data is coming in from an outside source.
-
-If you need a more complicated solution, you can return the autocompletion values as a list of hash references containing the keys C<value> and (optionally) C<label>:
+In this example, the "foo" field is autocompleted from names matched
+from the C<MyApp::Model::Foo> table. The match, in this case, matches
+any substring found in the database. I could have matched any item
+that starts with the string, ends with the string, matches other
+fields than the one returned, etc. It's up to you to decide.
+
+Note also that I have untainted the value coming in to make sure a
+malicious user doesn't get anyway. You should always perform a check
+like this when data is coming in from an outside source.
+
+If you need a more complicated solution, you can return the
+autocompletion values as a list of hash references containing the keys
+C<value> and (optionally) C<label>:
 
   return map { { value => $_->name, label => $_->label } }
             @{ $foos->items_array_ref };
 
-In this case, the labels will be shown to the client, but the selected value would be returned to your application.
+In this case, the labels will be shown to the client, but the selected
+value would be returned to your application.
 
 =cut
 
@@ -1205,7 +1253,8 @@
 
 =head1 SEE ALSO
 
-L<Jifty>, L<Jifty::API>, L<Jifty::Action::Record>, L<Jifty::Result>, L<Jifty::Param::Schema>, L<Jifty::Manual::Actions>
+L<Jifty>, L<Jifty::API>, L<Jifty::Action::Record>, L<Jifty::Result>,
+L<Jifty::Param::Schema>, L<Jifty::Manual::Actions>
 
 =head1 LICENSE
 

Modified: jifty/branches/autoversioning/lib/Jifty/Action/Record.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Action/Record.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Action/Record.pm	Sun Jul 22 21:13:55 2007
@@ -168,7 +168,7 @@
             $render_as = defined $render_as ? lc($render_as) : '';
 
             if ( defined (my $valid_values = $column->valid_values)) {
-                $info->{valid_values} = [ @$valid_values ];
+                $info->{valid_values} = $valid_values;
                 $info->{render_as}    = 'Select';
             } elsif ( defined $column->type && $column->type =~ /^bool/i ) {
                 $info->{render_as} = 'Checkbox';
@@ -217,7 +217,13 @@
                     # No need to generate arguments for
                     # JDBI::Collections, as we can't do anything
                     # useful with them yet, anyways.
-                    next;
+
+                    # However, if the column comes with a
+                    # "render_as", we can assume that the app
+                    # developer know what he/she is doing.
+                    # So we just render it as whatever specified.
+
+                    next unless $render_as;
                 }
             }
 
@@ -303,7 +309,7 @@
             }
 
             # If we're hand-coding a render_as, hints or label, let's use it.
-            for (qw(render_as label hints max_length mandatory sort_order)) {
+            for (qw(render_as label hints max_length mandatory sort_order container)) {
 
                 if ( defined (my $val = $column->$_) ) {
                     $info->{$_} = $val;
@@ -346,7 +352,7 @@
 
 sub possible_fields {
     my $self = shift;
-    return map { $_->name } grep { $_->type ne "serial" } $self->record->columns;
+    return map { $_->name } grep { $_->container || $_->type ne "serial" } $self->record->columns;
 }
 
 =head2 take_action

Modified: jifty/branches/autoversioning/lib/Jifty/Action/Record/Search.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Action/Record/Search.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Action/Record/Search.pm	Sun Jul 22 21:13:55 2007
@@ -3,7 +3,7 @@
 
 =head1 NAME
 
-Jifty::Action::Record::Search
+Jifty::Action::Record::Search - Automagic search action
 
 =head1 DESCRIPTION
 

Modified: jifty/branches/autoversioning/lib/Jifty/ClassLoader.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/ClassLoader.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/ClassLoader.pm	Sun Jul 22 21:13:55 2007
@@ -120,69 +120,82 @@
     # The quick check. We only want to handle things for our app
     return undef unless $module =~ /^$base/;
 
+    # If the module is the same as the base, build the application class
     if ( $module =~ /^(?:$base)$/ ) {
         return $self->return_class( "package " . $base . ";\n");
     }
+
+    # Handle most of the standard App::Class ISA Jifty::Class
     elsif ( $module =~ /^(?:$base)::(Record|Collection|Notification|
-                                      Dispatcher|Bootstrap|Upgrade|
+                                      Dispatcher|Bootstrap|Upgrade|CurrentUser|
                                       Handle|Event|Event::Model|Action|
                                       Action::Record::\w+)$/x ) {
         return $self->return_class(
                   "package $module;\n"
                 . "use base qw/Jifty::$1/; sub _autogenerated { 1 };\n"
             );
-    } elsif ( $module =~ /^(?:$base)::View/ ) {
+    } 
+    
+    # Autogenerate an empty View if none is defined
+    elsif ( $module =~ /^(?:$base)::View$/ ) {
         return $self->return_class(
                   "package $module;\n"
                 . "use Jifty::View::Declare -base; sub _autogenerated { 1 };\n"
             );
-    } elsif ( $module =~ /^(?:$base)::CurrentUser$/ ) {
-        return $self->return_class(
-                  "package $module;\n"
-                . "use base qw/Jifty::CurrentUser/; sub _autogenerated { 1 };\n"
-            );
-    } elsif ( $module =~ /^(?:$base)::Model::(\w+)Collection$/ ) {
+    } 
+    
+    # Autogenerate the Collection class for a Model
+    elsif ( $module =~ /^(?:$base)::Model::([^\.]+)Collection$/ ) {
         return $self->return_class(
                   "package $module;\n"
                 . "use base qw/@{[$base]}::Collection/;\n"
                 . "sub record_class { '@{[$base]}::Model::$1' }\n"
+                . "sub _autogenerated { 1 };\n"
             );
-    } elsif ( $module =~ /^(?:$base)::Event::Model::([^\.]+)$/ ) {
+    } 
+    
+    # Autogenerate the the event class for model changes
+    elsif ( $module =~ /^(?:$base)::Event::Model::([^\.]+)$/ ) {
+        
+        # Determine the model class and load it
         my $modelclass = $base . "::Model::" . $1;
         Jifty::Util->require($modelclass);
 
-        return undef unless eval { $modelclass->table };
+        # Don't generate an event unless it really is a model
+        return undef unless eval { $modelclass->isa('Jifty::Record') };
 
         return $self->return_class(
                   "package $module;\n"
                 . "use base qw/${base}::Event::Model/;\n"
                 . "sub record_class { '$modelclass' };\n"
-                . "sub autogenerated { 1 };\n"
+                . "sub _autogenerated { 1 };\n"
             );
-    } elsif ( $module =~ /^(?:$base)::Action::
+    } 
+    
+    # Autogenerate the record actions for a model
+    elsif ( $module =~ /^(?:$base)::Action::
                         (Create|Update|Delete|Search)([^\.]+)$/x ) {
-        my $modelclass = $base . "::Model::" . $2;
 
-        Jifty::Util->require($modelclass);
+        # Determine the model class and load it
+        my $modelclass = $base . "::Model::" . $2;
+        Jifty::Util->_require( module => $modelclass, quiet => 1);
 
-        local $@;
-            eval { $modelclass->table } ;
-        if(!$@) {
+        # Don't generate the action unless it really is a model
+        return undef unless eval { $modelclass->isa('Jifty::Record') };
 
         return $self->return_class(
                   "package $module;\n"
                 . "use base qw/$base\::Action::Record::$1/;\n"
                 . "sub record_class { '$modelclass' };\n"
-                . "sub autogenerated { 1 };\n"
+                . "sub _autogenerated { 1 };\n"
             );
-        }
 
     }
 
-    # This is if, not elsif because we might have $base::Action::Deleteblah 
+    # This is if, not elsif because we might have $base::Action::Deleteblah
     # that matches that last elsif clause but loses on the eval.
     if ( $module =~ /^(?:$base)::(Action|Notification)::(.*)$/x and not grep {$_ eq $base} map {ref} Jifty->plugins ) {
-        my $type = $1; 
+        my $type = $1;
         my $item = $2;
         # If we don't have the action in our own app, let's try the plugins
         # the app has loaded.
@@ -193,7 +206,7 @@
         return $self->return_class(
                   "package $module;\n"
                 . "use base qw/$class/;\n"
-                . "sub autogenerated { 1 };\n"
+                . "sub _autogenerated { 1 };\n"
             );
 
 
@@ -234,15 +247,15 @@
 
 sub require {
     my $self = shift;
-    
+
     my $base = $self->{base};
     # if we don't even have an application class, this trick will not work
-    return unless ($base); 
+    return unless ($base);
     Jifty::Util->require($base);
     Jifty::Util->require($base."::CurrentUser");
 
     my %models;
-    
+
 
     Jifty::Module::Pluggable->import(
         # $base goes last so we pull in the view class AFTER the model classes
@@ -256,7 +269,7 @@
     for my $full ($self->models) {
         $self->_require_model_related_classes($full);
     }
-        
+
 }
 
 sub _require_model_related_classes {
@@ -275,13 +288,13 @@
 
 Jifty supports model classes that aren't files on disk but instead records
 in your database. It's a little bit mind bending, but basically, you can
-build an application entirely out of the database without ever writing a 
-line of code(*). 
+build an application entirely out of the database without ever writing a
+line of code(*).
 
-* As of early 2007, this forward looking statement is mostly a lie. But we're 
+* As of early 2007, this forward looking statement is mostly a lie. But we're
 working on it.
 
-This method finds all database-backed models and instantiates jifty classes for 
+This method finds all database-backed models and instantiates jifty classes for
 them it returns a list of classnames of the models it created.
 
 =cut
@@ -308,10 +321,10 @@
 
 sub require_views {
     my $self = shift;
-    
+
     my $base = $self->{base};
     # if we don't even have an application class, this trick will not work
-    return unless ($base); 
+    return unless ($base);
     Jifty::Util->require($base."::View");
 }
 

Modified: jifty/branches/autoversioning/lib/Jifty/Config.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Config.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Config.pm	Sun Jul 22 21:13:55 2007
@@ -155,6 +155,9 @@
     # getting stuck in a default config file for an app
     $self->stash( Hash::Merge::merge( $self->defaults, $self->stash));
 
+    $self->stash($self->update_config($self->stash));
+
+
     # Finally, check for global postload hooks (these are used by the
     # test harness)
     $self->$Jifty::Config::postload()
@@ -264,16 +267,6 @@
             L10N       => {
                 PoDir => "share/po",
             },
-            Plugins => [
-            #  { LetMe               => {}, },
-                { SkeletonApp            => {}, },
-                { REST               => {}, },
-                { Halo               => {}, },
-                { ErrorTemplates     => {}, },
-                { OnlineDocs         => {}, },
-                { CompressedCSSandJS => {}, },
-                { AdminUI            => {}, }
-                ],
             Web        => {
                 Port => '8888',
                 BaseURL => 'http://localhost',
@@ -297,6 +290,62 @@
 }
 
 
+=head2 initial_config
+
+Returns a default guessed config for a new application
+
+=cut
+
+sub initial_config {
+    my $self = shift;
+    my $guess = $self->guess(@_);
+    $guess->{'framework'}->{'ConfigFileVersion'} = 2;
+
+    # These are the plugins which new apps will get by default
+            $guess->{'framework'}->{'Plugins'} = [
+              { LetMe               => {}, },
+                { SkeletonApp            => {}, },
+                { REST               => {}, },
+                { Halo               => {}, },
+                { ErrorTemplates     => {}, },
+                { OnlineDocs         => {}, },
+                { CompressedCSSandJS => {}, },
+                { AdminUI            => {}, }
+                ];
+    return $guess;
+}
+
+
+
+=head2 update_config  $CONFIG
+
+Takes an application's configuration as a hashref.  Right now, it just sets up
+plugins that match an older jifty version's defaults
+
+=cut
+
+sub update_config {
+    my $self = shift;
+    my $config = shift;
+    if ( $config->{'framework'}->{'ConfigFileVersion'} <2) {
+            # These are the plugins which old apps expect because their
+            # features used to be in the core.
+            unshift (@{$config->{'framework'}->{'Plugins'}}, 
+                { SkeletonApp            => {}, },
+                { REST               => {}, },
+                { Halo               => {}, },
+                { ErrorTemplates     => {}, },
+                { OnlineDocs         => {}, },
+                { CompressedCSSandJS => {}, },
+                { AdminUI            => {}, }
+            );
+    }
+
+    return $config;
+}
+
+
+
 =head2 defaults
 
 We have a couple default values that shouldn't be included in the
@@ -309,12 +358,14 @@
     my $self = shift;
     return {
         framework => {
+            ConfigFileVersion => '1',
             L10N => {
                 DefaultPoDir => Jifty::Util->share_root . '/po',
             },
             Web => {
                 DefaultStaticRoot => Jifty::Util->share_root . '/web/static',
                 DefaultTemplateRoot => Jifty::Util->share_root . '/web/templates',
+                SessionCookieName => 'JIFTY_SID_$PORT',
             },
         }
     };

Modified: jifty/branches/autoversioning/lib/Jifty/Continuation.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Continuation.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Continuation.pm	Sun Jul 22 21:13:55 2007
@@ -144,7 +144,7 @@
 =head2 call
 
 Call the continuation; this is generally done during request
-processing, after an actions have been run.
+processing, after actions have been run.
 L<Jifty::Request::Mapper>-controlled values are filled into the stored
 request based on the current request and response.  During the
 process, another continuation is created, with the filled-in results
@@ -156,6 +156,12 @@
 sub call {
     my $self = shift;
 
+    Jifty->log->debug("Redirect to @{[$self->request->path]} via continuation");
+    if (Jifty->web->request->argument('_webservice_redirect')) {
+	# for continuation - perform internal redirect under webservices.
+        Jifty->web->webservices_redirect($self->request->path);
+	return;
+    }
     # If we needed to fix up the path (it contains invalid
     # characters) then warn, because this may cause infinite
     # redirects
@@ -189,6 +195,7 @@
 
     # Redirect to right page if we're not there already
     Jifty->web->_redirect($next->request->path . "?J:RETURN=" . $next->id);
+    return 1;
 }
 
 =head2 return

Modified: jifty/branches/autoversioning/lib/Jifty/CurrentUser.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/CurrentUser.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/CurrentUser.pm	Sun Jul 22 21:13:55 2007
@@ -4,13 +4,14 @@
 package Jifty::CurrentUser;
 
 use base qw/Jifty::Object Class::Accessor::Fast/;
+use Scalar::Util qw();
 
-__PACKAGE__->mk_accessors(qw(is_superuser is_bootstrap_user user_object));
+__PACKAGE__->mk_accessors(qw(is_superuser is_bootstrap_user));
 
 
 =head1 NAME
 
-Jifty::CurrentUser
+Jifty::CurrentUser - Base class and basic implementation of current user object
 
 =head1 DESCRIPTION
 
@@ -98,6 +99,20 @@
 
 =cut
 
+sub user_object {
+    my $self = shift;
+    return $self->{'user_object'} unless @_;
+
+    $self->{'user_object'} = shift;
+    # protect ourself from circular refereces
+    if ( $self->{'user_object'}{'_current_user'} == $self ) {
+        Scalar::Util::weaken( $self->{'user_object'}{'_current_user'} )
+            unless Scalar::Util::isweak( $self->{'user_object'}{'_current_user'} );
+        $self->{'user_object'}{'_resurrect_current_user'} = 1;
+    }
+    return $self->{'user_object'};
+}
+
 =head2 id
 
 Returns C<0> if we don't have a L<user_object>.  When we I<do> have a
@@ -160,7 +175,7 @@
 sub username {
     my $self = shift;
     return undef unless ($self->user_object);
-    return($self->user_object->username(@_));
+    return($self->user_object->brief_description(@_));
 }
 
 =head2 auth_token

Modified: jifty/branches/autoversioning/lib/Jifty/DateTime.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/DateTime.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/DateTime.pm	Sun Jul 22 21:13:55 2007
@@ -16,6 +16,15 @@
 
 =cut
 
+BEGIN {
+    # we spent about 30% of the time in validate during 'require
+    # DateTime::Locale' which isn't necessary at all
+    require Params::Validate;
+    no warnings 'redefine';
+    local *Params::Validate::validate = sub { pop @_, return @_ };
+    require DateTime::Locale;
+}
+
 use base qw(Jifty::Object DateTime);
 
 
@@ -51,6 +60,7 @@
 sub current_user_has_timezone {
     my $self = shift;
     $self->_get_current_user();
+    return unless $self->current_user->can('user_object');
     my $user_obj = $self->current_user->user_object or return;
     my $f = $user_obj->can('time_zone') or return;
     return $f->($user_obj);

Modified: jifty/branches/autoversioning/lib/Jifty/Dispatcher.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Dispatcher.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Dispatcher.pm	Sun Jul 22 21:13:55 2007
@@ -160,7 +160,7 @@
 All wildcards in the C<$match> string becomes capturing regex patterns.  You
 can also pass in an array reference of matches, or a regex pattern.
 
-The C<$match> string may be qualified with a HTTP method name, such as
+The C<$match> string may be qualified with a HTTP method name or protocol, such as
 
 =over
 
@@ -176,6 +176,10 @@
 
 =item HEAD
 
+=item HTTPS
+
+=item HTTP
+
 =back
 
 =head2 on $match => $rule
@@ -263,6 +267,8 @@
 
     GET POST PUT HEAD DELETE OPTIONS
 
+    HTTPS HTTP
+
     plugin
 
     get next_rule last_rule
@@ -300,6 +306,9 @@
 sub DELETE ($)  { _qualify method => @_ }
 sub OPTIONS ($) { _qualify method => @_ }
 
+sub HTTPS ($)   { _qualify https  => @_ }
+sub HTTP ($)    { _qualify http   => @_ }
+
 sub plugin ($) { return { plugin => @_ } }
 
 our $CURRENT_STAGE;
@@ -929,6 +938,30 @@
     lc( $ENV{REQUEST_METHOD} ) eq lc($method);
 }
 
+=head2 _match_https
+
+Returns true if the current request is under SSL.
+
+=cut
+
+sub _match_https {
+    my $self = shift;
+    $self->log->debug("Matching request against HTTPS");
+    return exists $ENV{HTTPS} ? 1 : 0;
+}
+
+=head2 _match_http
+
+Returns true if the current request is not under SSL.
+
+=cut
+
+sub _match_http {
+    my $self = shift;
+    $self->log->debug("Matching request against HTTP");
+    return exists $ENV{HTTPS} ? 0 : 1;
+}
+
 sub _match_plugin {
     my ( $self, $plugin ) = @_;
     warn "Deferred check shouldn't happen";
@@ -1149,6 +1182,7 @@
     my $self     = shift;
     my $template = shift;
     my $showed   = 0;
+#    local $@;
     eval {
         foreach my $handler ( Jifty->handler->view_handlers ) {
             if ( Jifty->handler->view($handler)->template_exists($template) ) {
@@ -1166,8 +1200,13 @@
     my $err = $@;
 
     # Handle parse errors
+    $self->log->fatal("view class error: $err") if $err;
     if ( $err and not eval { $err->isa('HTML::Mason::Exception::Abort') } ) {
-
+        if ($template eq '/__jifty/error/mason_internal_error') {
+            $self->log->debug("can't render internal_error: $err");
+            $self->_abort;
+            return;
+        }
         # Save the request away, and redirect to an error page
         Jifty->web->response->error($err);
         my $c = Jifty::Continuation->new(
@@ -1176,8 +1215,6 @@
             parent   => Jifty->web->request->continuation,
         );
 
-        warn "$err";
-
         # Redirect with a continuation
         Jifty->web->_redirect( "/__jifty/error/mason_internal_error?J:C=" . $c->id );
     } elsif ($err) {

Modified: jifty/branches/autoversioning/lib/Jifty/Event.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Event.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Event.pm	Sun Jul 22 21:13:55 2007
@@ -9,7 +9,7 @@
 
 =head1 NAME
 
-Jifty::Event
+Jifty::Event - Event objects for publish/subscribe communication
 
 =head1 DESCRIPTION
 

Modified: jifty/branches/autoversioning/lib/Jifty/Event/Model.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Event/Model.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Event/Model.pm	Sun Jul 22 21:13:55 2007
@@ -9,7 +9,7 @@
 
 =head1 NAME
 
-Jifty::Event::Model
+Jifty::Event::Model - Events representing changes to records
 
 =head1 DESCRIPTION
 

Modified: jifty/branches/autoversioning/lib/Jifty/I18N.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/I18N.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/I18N.pm	Sun Jul 22 21:13:55 2007
@@ -44,12 +44,20 @@
 
 my $DynamicLH;
 
+our $loaded;
+
 sub new {
     my $class = shift;
     my $self  = {};
     bless $self, $class;
 
+    # XXX: this requires a full review, LML->get_handle is calling new
+    # on I18N::lang each time, but we really shouldn't need to rerun
+    # the import here.
+    return $self if $loaded;
+
     my @import = map {( Gettext => $_ )} _get_file_patterns();
+    ++$loaded;
 
     Locale::Maketext::Lexicon->import(
         {   '*' => \@import,

Modified: jifty/branches/autoversioning/lib/Jifty/LetMe.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/LetMe.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/LetMe.pm	Sun Jul 22 21:13:55 2007
@@ -84,7 +84,7 @@
     my $currentuser_object_class = Jifty->app_class("CurrentUser");
     my $u = $currentuser_object_class->new( email => $email )->user_object;
     # we want to be able to get at their auth token.
-    $u->current_user(Jifty->app_class('CurrentUser')->superuser);
+    $u->current_user( $currentuser_object_class->superuser );
     return $u;
 }
 

Modified: jifty/branches/autoversioning/lib/Jifty/Manual/Continuations.pod
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Manual/Continuations.pod	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Manual/Continuations.pod	Sun Jul 22 21:13:55 2007
@@ -167,11 +167,11 @@
 successful, calls the stored continuation, or, lacking one, redirects
 to C</protected>.
 
-As currently impelented, these redirect-from-dispatcher tangents works
+As currently implemented, these redirect-from-dispatcher tangents works
 exactly like rendered-as-links tangents, in that when they return,
 I<all> rules in the dispatcher are still executed from the start.
 Therefore the C<unless> guard in the C<before '/protected'> rule above
-is neccessary to prevent recursion.
+is necessary to prevent recursion.
 
 =head1 GORY DETAILS
 

Modified: jifty/branches/autoversioning/lib/Jifty/Manual/Cookbook.pod
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Manual/Cookbook.pod	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Manual/Cookbook.pod	Sun Jul 22 21:13:55 2007
@@ -1,6 +1,6 @@
 =head1 NAME
 
-Jifty::Manual::Cookbook
+Jifty::Manual::Cookbook - Recipes for common tasks in Jifty
 
 =head1 DESCRIPTION
 
@@ -177,7 +177,7 @@
 
     before qr'^/secret' => run {
         unless(Jifty->web->current_user->id) {
-            Jifty->web->tangent('/login');
+            Jifty->web->tangent(url => '/login');
         }
     };
 
@@ -400,6 +400,62 @@
         Jifty->web->out($image);
     };
 
+=head2 Create a many-to-many relationship
+
+You need to create two one-to-many relationships with a linking table as you normally would in pure SQL. First, create your linking table by running:
+
+  bin/jifty model --name LinkTable
+
+Modify the newly created C<MyApp::Model::LinkTable> class to add new columns linking back to either side of the table:
+
+  use MyApp::Record schema {
+      column left_table =>
+          refers_to MyApp::Model::LeftTable;
+      column right_table =>
+          refers_to MyApp::Model::RightTable;
+  };
+
+Then create links to the linking table in C<MyApp::Model::LeftTable>:
+
+  use MyApp::Record schema {
+      # other columns...
+      
+      column right_things =>
+          refers_to MyApp::Model::LinkTableCollection by 'left_table';
+  };
+
+Then create links to the linking table in C<MyApp::Model::RightTable>:
+
+  use MyApp::Record schema {
+      # other columns...
+      
+      column left_things =>
+          refers_to MyApp::Model::LinkTableCollection by 'right_table';
+  };
+
+Now, add your records. To create a relationship between a row the two tables:
+
+  my $left = MyApp::Model::LeftTable->new;
+  $left->load(1);
+
+  my $right = MyApp::Model::RightTable->new;
+  $right->laod(1);
+
+  my $link = MyApp::Model::LinkTable->new;
+  $link->create(
+      left_table  => $left,
+      right_table => $right,
+  );
+
+And to get all the "right things" from the left table, you need to make the extra hop in your loop:
+
+  my $links = $left->right_things;
+  while (my $link = $links->next) {
+      my $right = $link->right_table;
+  
+      # Do stuff with $right
+  }
+
 =for comment
 Document how to do this with Mason
 
@@ -426,4 +482,81 @@
 would be really cool to have access to all data of the action in
 this method, so you are welcome to post a better solution.
 
+=head2 Append a new region based upon the result of the last action using AJAX
+
+In the Administration Interface, you can create new items. You enter the information and then the newly created item is appended to the end of the list immediately without reloading the page. You can use this recipe to do something like this, or to modify the page however you need based upon the result of any server-side action.
+
+Render your action fields as you normally would. The key to the process is in the submit button. Here's how the L<Jifty::View::Declare::CRUD> does this, as of this writing:
+
+  Jifty->web->form->submit(
+      label   => 'Create',
+      onclick => [
+          { submit       => $create },
+          { refresh_self => 1 },
+          {   element =>
+                  Jifty->web->current_region->parent->get_element(
+                  'div.list'),
+              append => $self->fragment_for('view'),
+              args   => {
+                  object_type => $object_type,
+                  id => { result_of => $create, name => 'id' },
+              },
+          },
+      ]
+  );
+
+This could is embedded in a call to C<outs()> for use with L<Template::Declare> templating, but you could just as easily wrap the line above in C<< <% %> >> for use with Mason templates. The keys is each item in the list past to C<onclick>:
+
+  { submit => $create },
+
+This tells Jifty submit the form elements related to the action referenced by C<$create> only. Any other actions in the same form will be ignored.
+
+  { refresh_self => 1 },
+
+This tells the browser to refresh the current region (which will be the one containing the current submit button), so that the form can be reused. You could also modify this behavior to delete the region, if you wrote:
+
+  { delete => Jifty->web->current_region },
+
+The most complicated part is the most important:
+
+  {   element =>
+          Jifty->web->current_region->parent->get_element(
+          'div.list'),
+      append => $self->fragment_for('view'),
+      args   => {
+          object_type => $object_type,
+          id => { result_of => $create, name => 'id' },
+      },
+  },
+
+=over
+
+=item element
+
+The C<element> parameter tells the browser where to insert the new item. By using C<< Jifty->web->current_region->parent->get_element('div.list') >>, the new code will be appended to the first C<div> tag found with a C<list> class within the parent region. This assumes that you have added such an element to the parent region. 
+
+You could look up an arbitrary region using C<< Jifty->web->get_region('fully-qualified-region-name') >> if you don't want to use the parent of the current region.
+
+=item append
+
+The C<append> argument gives the path to the URL of the item to insert. By using C<append>, you are telling Jifty to add your new code to the end of the element given in C<element>. If you want to add it to the beginning, you can use C<prepend> instead.
+
+=item args
+
+Last, but not least, you need to send arguments to the URL related to the action being performed. These can be anything you need for the your template to render the required code. In this example, two arguments are passed: C<object_type> and C<id>. In the case of C<object_type> a known value is passed. In the case of C<id>, the result of the action is passed, which is the key to the whole deal:
+
+  id => { result_of => $create, name => 'id' },
+
+This line tells Jifty that you want to set the "id" paramter sent to the URL given in C<append>, to the "id" set when C<$create> is executed. That is, after running the action, Jifty will contact the URL and effectively perform:
+
+  set id => $create->result->content('id');
+
+It's a lot more complicated than that in actuality, but Jifty takes care of all the nasty details.
+
+=back
+
+If you want to use a custom action other than the built-in create and want to pass something back other than the "id", you just need to set the result into the appropriate key on the C<content> method of the L<Jifty::Result>.
+
+For more details on how you can customize this further, see L<Jifty::Manual::PageRegions>, L<Jifty::Web::Form::Element>, L<Jifty::Result>, L<Jifty::Action>, L<Jifty::Web::PageRegion>, L<Jifty::Web>, and L<Jifty::Request::Mapper>.
+
 =cut

Modified: jifty/branches/autoversioning/lib/Jifty/Mason/Halo.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Mason/Halo.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Mason/Halo.pm	Sun Jul 22 21:13:55 2007
@@ -7,7 +7,7 @@
 
 =head1 NAME
 
-Jifty::Mason::Halo
+Jifty::Mason::Halo - Class for drawing "halos" around page components
 
 =head1 DESCRIPTION
 

Modified: jifty/branches/autoversioning/lib/Jifty/Model/SessionCollection.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Model/SessionCollection.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Model/SessionCollection.pm	Sun Jul 22 21:13:55 2007
@@ -5,6 +5,12 @@
 
 use base qw/Jifty::Collection/;
 
+=head1 NAME
+
+Jifty::Model::SessionCollection - Specialized handling of the session collection
+
+=head2 METHODS
+
 =head2 record_class
 
 This deals with collections of L<Jifty::Model::Session>s.

Modified: jifty/branches/autoversioning/lib/Jifty/Module/Pluggable.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Module/Pluggable.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Module/Pluggable.pm	Sun Jul 22 21:13:55 2007
@@ -5,7 +5,7 @@
 
 =head1 NAME
 
-Jifty::Module::Pluggable
+Jifty::Module::Pluggable - Jifty-specific helper for Module::Pluggable
 
 
 =head1 DESCRIPTION
@@ -21,15 +21,15 @@
     To:       jesse at bestpractical.com
 
 On Mon, Oct 23, 2006 at 09:11:22PM -0700, Jesse Vincent said:
-does this thread make any sense to you? It looks like  
+does this thread make any sense to you? It looks like
 Module::Pluggable is interacting poorly with UNIVERSAL::require?
 
-Module::Pluggable used to to use UNIVERSAL::require but I switched 
+Module::Pluggable used to to use UNIVERSAL::require but I switched
 because I was trying to get rid of dependencies.
 
-I farmed the requiring stuff off to it's own _require method in order to 
-make it easy to subclass so that people could ovveride how the require 
-was done. 
+I farmed the requiring stuff off to it's own _require method in order to
+make it easy to subclass so that people could ovveride how the require
+was done.
 
 
 =head3  But Simon is lying...
@@ -51,17 +51,19 @@
     # Module::Pluggable::Object::_require expects a true value (the error message) on failure
     # On success, it expects you to return undef.
 
+    return if $module =~/\.#/;
+
     local $UNIVERSAL::require::ERROR;
 
     no warnings; # This is lexical and turns off exactly one warning below -- "Can't locate package in @ISA".
                  # (for some reason, "no warnings 'syntax'" does not work as advertised here.)
                  # Note that it does _not_ turn off warnings triggered in the $module itself.
     if ((not $module->require()) &&  ( $UNIVERSAL::require::ERROR !~ /^Can't locate/)) {
-        die $UNIVERSAL::require::ERROR;    
-    } 
+        die $UNIVERSAL::require::ERROR;
+    }
          # We'd prefer to use Jifty::Util->require() here, but it spews crazy warnings
 
     return $UNIVERSAL::require::ERROR;
-} 
+}
 
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Notification.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Notification.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Notification.pm	Sun Jul 22 21:13:55 2007
@@ -6,16 +6,22 @@
 use base qw/Jifty::Object Class::Accessor::Fast/;
 use Email::Send            ();
 use Email::MIME::Creator;
+use Email::MIME::CreateHTML;
+use Email::MIME::Modifier;
 
 __PACKAGE__->mk_accessors(
-    qw/body preface footer subject from _recipients _to_list to/);
+    qw/body html_body preface footer subject from _recipients _to_list to/);
+
+=head1 NAME
+
+Jifty::Notification - Send emails from Jifty
 
 =head1 USAGE
 
 It is recommended that you subclass L<Jifty::Notification> and
-override C<body>, C<subject>, C<recipients>, and C<from> for each
-message.  (You may want a base class to provide C<from>, C<preface>
-and C<footer> for example.)  This lets you keep all of your
+override C<body>, C<html-body>, C<subject>, C<recipients>, and C<from>
+for each message.  (You may want a base class to provide C<from>,
+C<preface> and C<footer> for example.)  This lets you keep all of your
 notifications in the same place.
 
 However, if you really want to make a notification type in code
@@ -74,8 +80,13 @@
 if mail was actually sent.  Note errors are not the only cause of mail
 not being sent -- for example, the recipients list could be empty.
 
-Be aware that if you haven't set C<recipients>, this will fail silently
-and return without doing anything useful.
+If you wish to send HTML mail, set C<html_body>.  If this is not set
+(for backwards compatibility) a plain-text email is sent.  If
+C<html_body> and C<body> are both set, a multipart mail is sent.  See
+L<Email::MIME::CreateHTML> for how this is done.
+
+Be aware that if you haven't set C<recipients>, this will fail
+silently and return without doing anything useful.
 
 =cut
 
@@ -86,18 +97,40 @@
         map { ( $_->can('email') ? $_->email : $_ ) } grep {$_} @recipients );
     $self->log->debug("Sending a ".ref($self)." to $to"); 
     return unless ($to);
-
+    my $message = "";
     my $appname = Jifty->config->framework('ApplicationName');
 
-    my $message = Email::MIME->create(
-        header => [
-            From    => ($self->from    || _('%1 <%2>' , $appname, Jifty->config->framework('AdminEmail'))) ,
-            To      => $to,
-            Subject => Encode::encode('MIME-Header', $self->subject || _("A notification from %1!",$appname )),
-        ],
-        attributes => { charset => 'UTF-8' },
-        parts => $self->parts
-    );
+    my %attrs = ( charset => 'UTF-8' );
+
+    if ($self->html_body) {
+      $message = Email::MIME->create_html(
+					     header => [
+							From    => ($self->from    || _('%1 <%2>' , $appname, Jifty->config->framework('AdminEmail'))) ,
+							To      => $to,
+							Subject => Encode::encode('MIME-Header', $self->subject || _("A notification from %1!",$appname )),
+						       ],
+					     attributes => \%attrs,
+                         text_body_attributes => \%attrs,
+                         body_attributes => \%attrs,
+					     text_body => Encode::encode_utf8($self->full_body),
+					     body => Encode::encode_utf8($self->full_html),
+                         embed => 0,
+                         inline_css => 0
+					    );
+        # Since the containing messsage will still be us-ascii otherwise
+        $message->charset_set( $attrs{'charset'} );
+    } else {
+            $message = Email::MIME->create(
+					     header => [
+							From    => ($self->from    || _('%1 <%2>' , $appname, Jifty->config->framework('AdminEmail'))) ,
+							To      => $to,
+							Subject => Encode::encode('MIME-Header', $self->subject || _("A notification from %1!",$appname )),
+						       ],
+					     attributes => \%attrs,
+					     
+					     parts => $self->parts
+					    );
+	  }
     $message->encoding_set('8bit')
         if (scalar $message->parts == 1);
     $self->set_headers($message);
@@ -259,6 +292,17 @@
   return join( "\n", grep { defined } $self->preface, $self->body, $self->footer );
 }
 
+=head2 full_html
+
+Same as full_body, but with HTML.
+
+=cut
+
+sub full_html {
+  my $self = shift;
+  return join( "\n", grep { defined } $self->preface, $self->html_body, $self->footer );
+}
+
 =head2 parts
 
 The parts of the message.  You want to override this if you want to

Modified: jifty/branches/autoversioning/lib/Jifty/Object.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Object.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Object.pm	Sun Jul 22 21:13:55 2007
@@ -5,7 +5,11 @@
 
 use Log::Log4perl ();
 
-=head1 Jifty::Object
+=head1 NAME
+
+Jifty::Object - Base class for most of Jifty's objects
+
+=head1 DESCRIPTION
 
 C<Jifty::Object> is the superclass of most of Jifty's objects.  It is
 used to provide convenient accessors to important global objects like
@@ -16,7 +20,7 @@
 thus, we will not define C<new> or C<_init> in C<Jifty::Object>.  We
 do assume, however, that C<$self> is a blessed hash reference.
 
-=cut
+=head1 METHODS
 
 =head2 current_user [USER]
 

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin.pm	Sun Jul 22 21:13:55 2007
@@ -98,8 +98,7 @@
         eval { $self->{share} = module_dir($class) };
     }
     unless ( $self->{share} ) {
-        local $@; # We're just avoiding File::ShareDir's failure behaviour of dying
-        eval { $self->{share} = module_dir('Jifty') };
+        $self->{share} = Jifty::Util->share_root;
         if ( $self->{'share'} ) {
             my $class_to_path = $class;
             $class_to_path =~ s|::|/|g;
@@ -184,4 +183,56 @@
     return ();
 }
 
+=head2 version
+
+Returns the database version of the plugin. Needs to be bumped any time the database schema needs to be updated. Plugins that do not directly define any models don't need to worry about this.
+
+=cut
+
+sub version {
+    return '0.0.1';
+}
+
+=head2 bootstrapper
+
+Returns the name of the class that can be used to bootstrap the database models. This normally returns the plugin's class name with C<::Bootstrap> added to the end. Plugin bootstrappers can be built in exactly the same way as application bootstraps.
+
+See L<Jifty::Bootstrap>.
+
+=cut
+
+sub bootstrapper {
+    my $self = shift;
+    my $class = ref $self;
+    return $class . '::Bootstrap';
+}
+
+=head2 upgrade_class
+
+Returns the name of the class that can be used to upgrade the database models and schema (such as adding new data, fixing default values, and renaming columns). This normally returns the plugin's class name with C<::Upgrade> added to the end. Plugin upgraders can be built in exactly the same was as application upgrade classes.
+
+See L<Jifty::Upgrade>.
+
+=cut
+
+sub upgrade_class {
+    my $self = shift;
+    my $class = ref $self;
+    return $class . '::Upgrade';
+}
+
+=head2 table_prefix
+
+Returns a prefix that will be placed in the front of all table names for plugin models. Be default, the plugin name is converted to an identifier based upon the class name.
+
+=cut
+
+sub table_prefix {
+    my $self = shift;
+    my $class = ref $self;
+    $class =~ s/\W+/_/g;
+    $class .= '_';
+    return lc $class;
+}
+
 1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,7 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::ActorMetadata;
+use base qw/Jifty::Plugin/;
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata/Mixin/Model/ActorMetadata.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/ActorMetadata/Mixin/Model/ActorMetadata.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,114 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::ActorMetadata::Mixin::Model::ActorMetadata;
+use Jifty::DBI::Schema;
+use base 'Jifty::DBI::Record::Plugin';
+
+our @EXPORT = qw(current_user_can);
+
+=head1 NAME
+
+Jifty::Plugin::ActorMetadata::Mixin::Model::ActorMetadata - ActorMetadata mixin
+
+=head1 SYNOPSIS
+
+  package MyApp::Model::CoffeeShop;
+  use Jifty::DBI::Schema;
+  use MyApp::Record schema {
+      # custom column defrinitions
+  };
+
+  use Jifty::Plugin::ActorMetadata::Mixin::Model::ActorMetadata; # created_by, created_on, updated_on
+
+=head1 DESCRIPTION
+
+=head1 SCHEMA
+
+This mixin adds the following columns to the model schema:
+
+=head2 created_by
+
+=head2 created_on
+
+=head2 updated_on
+
+=cut
+
+# XXX: move this to somewhere
+my $app_user;
+BEGIN {
+
+# Do not call ->app_class within the schmea {} block.
+$app_user = Jifty->app_class('Model', 'User');
+Jifty::DBI::Schema->register_types(
+    Date =>
+        sub { type is 'date', input_filters are qw/Jifty::DBI::Filter::Date/ },
+    Time =>
+        sub { type is 'time', input_filters are qw/Jifty::DBI::Filter::Time/ },
+    DateTime => sub {
+        type is 'datetime',
+        input_filters are qw/Jifty::DBI::Filter::DateTime/ },
+    TimeStamp => sub {
+        type is 'timestamp',
+        filters are qw( Jifty::Filter::DateTime Jifty::DBI::Filter::DateTime),
+    }
+);
+}
+
+use Jifty::Record schema {
+
+column created_by =>
+  render_as 'hidden',
+  refers_to $app_user;
+
+column created_on => is TimeStamp,
+  render_as 'hidden';
+column updated_on => is TimeStamp,
+  render_as 'hidden';
+
+};
+
+=head1 METHODS
+
+# XXX: podcoverage should count parent classes.  these pods are useless
+
+=head2 register_triggers
+
+Adds the triggers to the model this mixin is added to.
+
+=cut
+
+sub register_triggers {
+    my $self = shift;
+    $self->add_trigger(name => 'before_create', callback => \&before_create);
+}
+
+sub before_create {
+    my $self = shift;
+    my $args = shift;
+
+    $args->{'created_by'} = $self->current_user->id;
+    $args->{'created_on'} = $args->{'updated_on'} = Jifty::DateTime->now;
+
+    return 1;
+}
+
+# XXX: Move this to an abortable trigger
+sub current_user_can {
+    my $self = shift;
+    my $action = shift;
+    my %args = (@_);
+
+    if ($action eq 'create') {
+        return undef unless ($self->current_user and $self->current_user->id);
+    }
+
+    if ($action eq 'update' or $action eq 'delete') {
+        return undef unless ($self->current_user and $self->current_user->id eq $self->created_by->id);
+    }
+
+    return 1;
+}
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,112 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Authentication::Facebook;
+use base qw/Jifty::Plugin/;
+
+use WWW::Facebook::API;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Facebook
+
+=head2 DESCRIPTION
+
+Provides standalone Facebook authentication for your Jifty application.
+It adds the columns C<facebook_name>, C<facebook_uid>, C<facebook_session>,
+and C<facebook_session_expires> to your User model.
+
+=head1 SYNOPSIS
+
+In your jifty config.yml under the C<framework> section:
+
+    Plugins:
+        - Authentication::Facebook:
+            api_key: xxx
+            secret: xxx
+
+You may set any options which the C<new> method of L<WWW::Facebook::API>
+understands.
+
+In your User model, you'll need to include the line
+
+    use Jifty::Plugin::Authentication::Facebook::Mixin::Model::User;
+
+B<after> your schema definition (which may be empty).  You may also wish
+to include
+
+    sub _brief_description { 'facebook_name' }
+
+To use the user's Facebook name as their description.
+
+See L<Jifty::Plugin::Authentication::Facebook::View> for the provided templates
+and L<Jifty::Plugin::Authentication::Facebook::Dispatcher> for the URLs handled.
+
+=cut
+
+our %CONFIG = ( );
+
+=head2 init
+
+=cut
+
+sub init {
+    my $self = shift;
+    %CONFIG  = @_;
+}
+
+=head2 api
+
+Generates a new L<WWW::Facebook::API> for the current user
+
+=cut
+
+sub api {
+    my $self = shift;
+    my $api  = WWW::Facebook::API->new( %CONFIG );
+    
+    if ( Jifty->web->current_user->id ) {
+        my $user = Jifty->web->current_user->user_object;
+        $api->session(
+            uid     => $user->facebook_uid,
+            key     => $user->facebook_session,
+            expires => $user->facebook_session_expires
+        ) if $user->facebook_uid;
+    }
+
+    return $api;
+}
+
+=head2 get_login_url
+
+Gets the login URL, preserving continuations
+
+=cut
+
+sub get_login_url {
+    my $self = shift;
+    my $next = '/facebook/callback';
+ 
+    if ( Jifty->web->request->continuation ) {
+        $next .= '?J:C=' . Jifty->web->request->continuation->id;
+    }
+    return $self->api->get_login_url( next => $next );
+}
+
+=head2 get_link_url
+
+Gets the login URL used for linking, preserving continuations
+
+=cut
+
+sub get_link_url {
+    my $self = shift;
+    my $next = '/facebook/callback_link';
+ 
+    if ( Jifty->web->request->continuation ) {
+        $next .= '?J:C=' . Jifty->web->request->continuation->id;
+    }
+    return $self->api->get_login_url( next => $next );
+}
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Action/LinkFacebookUser.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,75 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Facebook::Action::LinkFacebookUser;
+
+=cut
+
+package Jifty::Plugin::Authentication::Facebook::Action::LinkFacebookUser;
+use base qw/Jifty::Action/;
+
+=head1 ARGUMENTS
+
+=head2 auth_token
+
+=cut
+
+use Jifty::Param::Schema;
+use Jifty::Action schema {
+    param auth_token =>
+        type is 'text',
+        is mandatory;
+};
+
+=head1 METHODS
+
+=head2 take_action
+
+Get the session key using the Facebook API.  Link to current user.
+
+=cut
+
+sub take_action {
+    my $self     = shift;
+    my ($plugin) = Jifty->find_plugin('Jifty::Plugin::Authentication::Facebook');
+    my $api      = $plugin->api;
+
+    if ( not Jifty->web->current_user->id ) {
+        $self->result->error(_("You must be logged in to link your user to your Facebook account."));
+        return;
+    }
+
+    # Get the session
+    $api->auth->get_session( $self->argument_value('auth_token') );
+
+    my $user = Jifty->web->current_user->user_object;
+
+    my $name = $api->users->get_info(
+        uids    => $api->session_uid,
+        fields  => 'name'
+    )->[0]{'name'};
+
+    # Set data
+    $user->__set( column => 'facebook_name', value => $name );
+    $user->__set( column => 'facebook_uid',  value => $api->session_uid );
+    $user->__set( column => 'facebook_session', value => $api->session_key );
+    $user->__set( column => 'facebook_session_expires', value => $api->session_expires );
+
+    # Success!
+    $self->report_success;
+
+    return 1;
+}
+
+=head2 report_success
+
+=cut
+
+sub report_success {
+    my $self = shift;
+    $self->result->message(_("Your account has been successfully linked to your Facebook user %1!", Jifty->web->current_user->user_object->facebook_name ));
+}
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Action/LoginFacebookUser.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,106 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Facebook::Action::LoginFacebookUser;
+
+=cut
+
+package Jifty::Plugin::Authentication::Facebook::Action::LoginFacebookUser;
+use base qw/Jifty::Action/;
+
+=head1 ARGUMENTS
+
+=head2 auth_token
+
+=cut
+
+use Jifty::Param::Schema;
+use Jifty::Action schema {
+    param auth_token =>
+        type is 'text',
+        is mandatory;
+};
+
+=head1 METHODS
+
+=head2 take_action
+
+Get the session key using the Facebook API.  Check for existing user.
+If none, autocreate.  Login user.
+
+=cut
+
+sub take_action {
+    my $self    = shift;
+    my ($plugin)  = Jifty->find_plugin('Jifty::Plugin::Authentication::Facebook');
+    my $api       = $plugin->api;
+
+    # Get the session
+    $api->auth->get_session( $self->argument_value('auth_token') );
+
+    # Load up the user
+    my $current_user = Jifty->app_class('CurrentUser');
+    my $user = $current_user->new( facebook_uid => $api->session_uid );
+
+    # Autocreate the user if necessary
+    if ( not $user->id ) {
+        my $action = Jifty->web->new_action(
+            class           => 'CreateUser',
+            current_user    => $current_user->superuser,
+            arguments       => {
+                facebook_uid     => $api->session_uid,
+                facebook_session => $api->session_key,
+                facebook_session_expires => $api->session_expires
+            }
+        );
+        $action->run;
+
+        if ( not $action->result->success ) {
+            # Should this be less "friendly"?
+            $self->result->error(_("Sorry, something weird happened (we couldn't create a user for you).  Try again later."));
+            return;
+        }
+
+        $user = $current_user->new( facebook_uid => $api->session_uid );
+    }
+
+    my $name = $api->users->get_info(
+        uids    => $api->session_uid,
+        fields  => 'name'
+    )->[0]{'name'};
+
+    my $u = $user->user_object;
+
+    # Always check name
+    $u->__set( column => 'facebook_name', value => $name )
+        if not defined $u->facebook_name or $u->facebook_name ne $name;
+
+    # Update, just in case
+    if ( $u->__value('facebook_session') ne $api->session_key ) {
+        $u->__set( column => 'facebook_session', value => $api->session_key );
+        $u->__set( column => 'facebook_session_expires', value => $api->session_expires );
+    }
+
+    # Login!
+    Jifty->web->current_user( $user );
+    Jifty->web->session->expires( (not $api->session_expires) ? '+1y' : undef );
+    Jifty->web->session->set_cookie;
+
+    # Success!
+    $self->report_success;
+
+    return 1;
+}
+
+=head2 report_success
+
+=cut
+
+sub report_success {
+    my $self = shift;
+    $self->result->message(_("Hi %1!", Jifty->web->current_user->user_object->facebook_name ));
+}
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Dispatcher.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,70 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Authentication::Facebook::Dispatcher;
+use Jifty::Dispatcher -base;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Facebook::Dispatcher
+
+=head1 DESCRIPTION
+
+All the dispatcher rules jifty needs to support L<Jifty::Authentication::Facebook>
+
+=head1 RULES
+
+=head2 before '/facebook/callback'
+
+Handles the login callback.  You probably don't need to worry about this.
+
+=cut
+
+before qr'^/facebook/callback(_link)?' => run {
+    my $link    = $1 ? 1 : 0;
+    my $action  = $link ? 'LinkFacebookUser' : 'LoginFacebookUser';
+    my $moniker = $link ? 'facebooklink'     : 'facebooklogin';
+
+    Jifty->web->request->add_action(
+        moniker   => $moniker,
+        class     => $action,
+        arguments => {
+            auth_token => get('auth_token'),
+        }
+    );
+    if ( Jifty->web->request->continuation ) {
+        Jifty->web->request->continuation->call;
+    }
+    else {
+        redirect '/';
+    }
+};
+
+=head2 before '/facebook/force_login'
+
+Redirects user to the Facebook login page.  Useful if you want to skip
+prompting the user to login on your app.
+
+=cut
+
+before '/facebook/force_login' => run {
+    my ($plugin) = Jifty->find_plugin('Jifty::Plugin::Authentication::Facebook');
+    Jifty->web->_redirect( $plugin->get_login_url );
+};
+
+=head2 before '/facebook/logout'
+
+Directing a user here will log him out of the app and Facebook.
+
+=cut
+
+before '/facebook/logout' => run {
+    if ( Jifty->web->current_user->id ) {
+        Jifty->web->current_user( undef );
+        my ($plugin) = Jifty->find_plugin('Jifty::Plugin::Authentication::Facebook');
+        $plugin->api->auth->logout;
+    };
+    redirect '/';
+};
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Mixin/Model/User.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/Mixin/Model/User.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,39 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Authentication::Facebook::Mixin::Model::User;
+use Jifty::DBI::Schema;
+use base 'Jifty::DBI::Record::Plugin';
+
+use Jifty::Plugin::Authentication::Facebook::Record schema {
+
+    column facebook_name => 
+        type is 'text';
+
+    column facebook_uid => 
+        type is 'int',
+        is immutable,
+        is distinct;
+
+    column facebook_session =>
+        type is 'text';
+
+    column facebook_session_expires =>
+        type is 'int';
+
+};
+
+=head2 set_facebook_uid INT
+
+Sets the user's Facebook ID
+
+=cut
+
+sub set_facebook_uid {
+    my $self = shift;
+    my $id   = shift;
+    $self->_set( column => 'facebook_uid', value => $id );
+}
+
+1;
+

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/View.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Facebook/View.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,49 @@
+use warnings;
+use strict;
+package Jifty::Plugin::Authentication::Facebook::View;
+
+use Jifty::View::Declare -base;
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Facebook::View
+
+=head1 DESCRIPTION
+
+Provides the Facebook login fragment for L<Jifty::Plugin::Authentication::Facebook>
+
+=head2 /facebook/login
+
+This fragment shows the standard Facebook button used for web login.
+
+=cut
+
+template '/facebook/login' => sub {
+    my ($plugin) = Jifty->find_plugin('Jifty::Plugin::Authentication::Facebook');
+    div {{ id is 'facebook_login' };
+        span { _("Login to Facebook now to get started!") };
+        a {{ href is $plugin->get_login_url };
+            img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' }};
+        };
+    };
+};
+
+=head2 /facebook/link
+
+This fragment shows the standard Facebook login button, prompting the user to
+link his account.
+
+=cut
+
+template '/facebook/link' => sub {
+    my ($plugin) = Jifty->find_plugin('Jifty::Plugin::Authentication::Facebook');
+    div {{ id is 'facebook_link' };
+        span { _("Login to Facebook now to link it with your current account!") };
+        a {{ href is $plugin->get_link_url };
+            img {{ src is 'http://static.ak.facebook.com/images/devsite/facebook_login.gif', border is '0' }};
+        };
+    };
+};
+
+
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password.pm	Sun Jul 22 21:13:55 2007
@@ -4,23 +4,17 @@
 package Jifty::Plugin::Authentication::Password;
 use base qw/Jifty::Plugin/;
 
-# Your plugin goes here.  If takes any configuration or arguments, you
-# probably want to override L<Jifty::Plugin/init>.
-
 =head1 NAME
 
-Jifty::Plugin::Authentication::Password
+Jifty::Plugin::Authentication::Password - password authentication plugin
 
 =head1 DESCRIPTION
 
-When finished, this plugin will provide password authentication for 
-your Jifty application. (It adds a "password" column to your "User" model class).
-
-Right now, it's useless and should be ignored.
+B<CAUTION:> This plugin is experimental.
 
+This may be combined with the L<Jifty::Plugin::User> and L<Jifty::Plugin::LetMe> plugins to provide user accounts and form-based password authentication to your application.
 
-=cut
-
+=head2 METHODS
 
 =head2 prereq_plugins
 
@@ -33,4 +27,15 @@
     return ('User', 'LetMe');
 }
 
+=head1 SEE ALSO
+
+L<Jifty::Manual::AccessControl>, L<Jifty::Plugin::User>, L<Jifty::Plugin::LetMe>, L<Jifty::Plugin::Authentication::Password::Mixin::Model::User>
+
+=head1 LICENSE
+
+Jifty is Copyright 2005-2007 Best Practical Solutions, LLC.
+Jifty is distributed under the same terms as Perl itself.
+
+=cut
+
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm	Sun Jul 22 21:13:55 2007
@@ -45,9 +45,7 @@
 sub setup {
     my $self = shift;
     my $LoginUser   = Jifty->app_class('Model', 'User');
-        my $CurrentUser   = Jifty->app_class('CurrentUser');
-
-
+    my $CurrentUser = Jifty->app_class('CurrentUser');
 
     $self->user_object(
         $LoginUser->new( current_user => $CurrentUser->superuser ) );
@@ -63,9 +61,8 @@
     my $self  = shift;
     my $email = shift;
 
-    my $LoginUser   = "Jifty::Plugin::Authentication::Password::Model::User";
-        my $CurrentUser = "Jifty::Plugin::Authentication::Password::CurrentUser";
-
+    my $LoginUser   = Jifty->app_class('Model', 'User');
+    my $CurrentUser = Jifty->app_class('CurrentUser');
 
     return $self->validation_error(
         address => _("That doesn't look like an email address.") )

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm	Sun Jul 22 21:13:55 2007
@@ -4,25 +4,22 @@
 package Jifty::Plugin::Authentication::Password::Dispatcher;
 use Jifty::Dispatcher -base;
 
-# Put any plugin-specific dispatcher rules here.
-
-
 =head1 NAME
 
-Jifty::Plugin::Authentication::Password::Dispatcher
+Jifty::Plugin::Authentication::Password::Dispatcher - password plugin dispatcher
 
 =head1 DESCRIPTION
 
 All the dispatcher rules jifty needs to support L<Jifty::Authentication::Password/>
 
-=cut
-
-
 =head1 RULES
 
-
 =head2 before logout
 
+Logout and return home.
+
+See L<Jifty::Plugin::Authentication::Password::Action::Logout>.
+
 =cut
 
 before 'logout' => run {
@@ -35,6 +32,8 @@
 
 =head2 before *
 
+Setup the navigation menu for login or logout.
+
 =cut
 
 before '*' =>  run {
@@ -47,7 +46,11 @@
 
 };
 
-=head2 on qr/^(?:passwordreminder|signup)$/ 
+=head2 on qr/^(?:passwordreminder|signup|lost_password)$/ 
+
+Redirect to home if logged.
+
+Request a password reminder or signup for an account otherwise.
 
 =cut
 
@@ -58,6 +61,10 @@
 
 =head2 on login
 
+Redirect to home if logged.
+
+Show the login form otherwise.
+
 =cut
 
 before qr|^/(?:login)$| => run {
@@ -65,12 +72,22 @@
     set 'next' => Jifty->web->request->continuation || Jifty::Continuation->new( request => Jifty::Request->new( path => "/" ) );
 };
 
+=head2 before reset_lost_password
+
+Request a password reset.
+
+=cut
+
 before qr|(?:reset_lost_password)| => run {
     set 'next' => Jifty->web->request->continuation || Jifty::Continuation->new( request => Jifty::Request->new( path => "/" ) );
 };
 # Send a password reminder for a lost password
 
-=head2 on passwordreminder
+=head2 before passwordreminder
+
+Request a new password reminder to be sent by email.
+
+See L<Jifty::Plugin::Authentication::Password::Action::SendPasswordReminder>.
 
 =cut
 
@@ -79,9 +96,11 @@
 };
 
 
-=head2 on signup
+=head2 before signup
 
-# Sign up for an account
+Sign up for an account.
+
+See L<Jifty::Plugin::Authentication::Password::Action::Signup>.
 
 =cut
 
@@ -90,9 +109,11 @@
 
 };
 
-=head2 on login
+=head2 before login
+
+Login to your account.
 
-Login
+See L<Jifty::Plugin::Authentication::Password::Action::Login>.
 
 =cut
 
@@ -102,6 +123,8 @@
 
 =head2 not_logged_in_nav
 
+Adds the login and signup links to the navigation menu.
+
 =cut
 
 sub not_logged_in_nav {
@@ -119,6 +142,8 @@
 
 =head2 logged_in_nav
 
+Adds the logout link to the navigation menu.
+
 =cut
 
 sub logged_in_nav {
@@ -130,5 +155,15 @@
 
 }
 
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Authentication::Password>, L<Jifty::Plugin::Authentication::Password::View>
+
+=head1 COPYRIGHT
+
+Jifty is Copyright 2005-2007 Best Practical Solutions, LLC.
+Jifty is distributed under the same terms as Perl itself.
+
+=cut
 
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm	Sun Jul 22 21:13:55 2007
@@ -7,7 +7,41 @@
 
 use Digest::MD5 qw'';
 
-our @EXPORT = qw(password_is hashed_password_is regenerate_auth_token);
+our @EXPORT = qw(password_is hashed_password_is regenerate_auth_token has_alternative_auth);
+
+=head1 NAME
+
+Jifty::Plugin::Authentication::Password::Mixin::Model::User - password plugin user mixin model
+
+=head1 SYNOPSIS
+
+  package MyApp::Model::User;
+  use Jifty::DBI::Schema;
+  use MyApp::Record schema {
+      # custom column defrinitions
+  };
+
+  use Jifty::Plugin::User::Mixin::Model::User; # name, email, email_confirmed
+  use Jifty::Plugin::Authentication::Password::Mixin::Model::User;
+  # ^^ password, auth_token
+
+=head1 DESCRIPTION
+
+This mixin model is added to the application's account model for use with the password authentication plugin. This mixin should be used in combination with L<Jifty::Plugin::User::Mixin::Model::User>.
+
+=head1 SCHEMA
+
+This mixin adds the following columns to the model schema:
+
+=head2 auth_token
+
+This is a unique identifier used when confirming a user's email account and recovering a lost password.
+
+=head2 password
+
+This is the user's password. It will be stored in the database after being processed through L<Digest::MD5>, so the password cannot be directly recovered from the database.
+
+=cut
 
 use Jifty::Plugin::Authentication::Password::Record schema {
 
@@ -21,7 +55,6 @@
 
 
 column password =>
-  is mandatory,
   is unreadable,
   label is _('Password'),
   type is 'varchar',
@@ -32,6 +65,14 @@
 
 };
 
+=head1 METHODS
+
+=head2 register_triggers
+
+Adds the triggers to the model this mixin is added to.
+
+=cut
+
 sub register_triggers {
     my $self = shift;
     $self->add_trigger(name => 'after_create', callback => \&after_create);
@@ -61,7 +102,9 @@
 =head2 hashed_password_is HASH TOKEN
 
 Check if the given I<HASH> is the result of hashing our (already
-salted and hashed) password with I<TOKEN>
+salted and hashed) password with I<TOKEN>.
+
+This can be used in cases where the pre-hashed password is sent during login as an additional security precaution (such as could be done via Javascript).
 
 =cut
 
@@ -77,7 +120,8 @@
 
 =head2 validate_password
 
-Makes sure that the password is six characters long or longer.
+Makes sure that the password is six characters long or longer, unless
+we have alternative means to authenticate.
 
 =cut
 
@@ -85,12 +129,22 @@
     my $self      = shift;
     my $new_value = shift;
 
+    return 1 if $self->has_alternative_auth();
+
     return ( 0, _('Passwords need to be at least six characters long') )
         if length($new_value) < 6;
 
     return 1;
 }
 
+=head2 after_create
+
+This trigger is added to the account model. It automatically sends a notification email to the user for password confirmation.
+
+See L<Jifty::Plugin::Authentication::Password::Notification::ConfirmEmail>.
+
+=cut
+
 
 sub after_create {
     my $self = shift;
@@ -102,9 +156,17 @@
     } else {
         warn  $self->id . " " .$self->email;
     }
+}
 
+=head2 has_alternative_auth
 
-}
+If your model supports other means of authentication, you should have
+this method return true, so the C<password> field can optionally be
+null and authentication with password is disabled in that case.
+
+=cut
+
+sub has_alternative_auth { }
 
 =head2 after_set_password
 
@@ -133,7 +195,16 @@
     $self->__set(column => 'auth_token', value => $auth_token);
 }
 
+=head1 SEE ALSO
 
+L<Jifty::Plugin::Authentication::Password>, L<Jifty::Plugin::User::Mixin::Model>
+
+=head1 LICENSE
+
+Jifty is Copyright 2005-2007 Best Practical Solutions, LLC.
+Jifty is distributed under the same terms as Perl itself.
+
+=cut
 
 1;
 

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/View.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/View.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Authentication/Password/View.pm	Sun Jul 22 21:13:55 2007
@@ -4,30 +4,42 @@
 
 =head1 NAME
 
-Jifty::Plugin::Authentication::Password::Login::View
+Jifty::Plugin::Authentication::Password::View - views for password plugin
 
 =head1 DESCRIPTION
 
-This code is only useful on the new Jifty "Declarative tempaltes" branch. It shouldn't get in the way 
-if you're running a traditional (0.610 or before) Jifty.
+This code is only useful on the new Jifty "Declarative templates" branch. It shouldn't get in the way if you're running a traditional (0.610 or before) Jifty.
+
+=begin comment
+
+Is the above really true or need to said anymore? -- Sterling
+
+=end comment
+
+This provides the templates for the pages and forms used by the password authentication plugin.
 
 =cut
 
 package Jifty::Plugin::Authentication::Password::View;
-use HTML::Entities ();
 use Jifty::View::Declare -base;
 
 { no warnings 'redefine';
-sub page (&) {
+sub page (&;$) {
     no strict 'refs'; 
     BEGIN {Jifty::Util->require(Jifty->app_class('View'))};
-    &{Jifty->app_class('View') . "::page"}(@_);
+    Jifty->app_class('View')->can('page')->(@_);
 }
 }
 
+=head1 TEMPLATES
+
+=head2 signup
+
+Displays a sign-up form.
+
+=cut
 
-template 'signup' => page {
-    title is _('Sign up');
+template 'signup' => page { title => _('Sign up') } content {
     my ( $action, $next ) = get(qw(action next));
     Jifty->web->form->start( call => $next );
     render_param( $action => 'name' , focus => 1);
@@ -36,11 +48,26 @@
     Jifty->web->form->end();
 };
 
-template login => page {
-    { title is _('Login!') };
-    show('login_widget');
+=head2 login
+
+Displays the login form.
+
+=cut
+
+template login => page { title => _('Login!') } content {
+    show('/login_widget');
 };
 
+=head2 login_widget
+
+A handy template for embedding the login form. Just include it in your templates via:
+
+  show('/login_widget');
+
+See L<Jifty::Plugin::Authentication::Password::Action::Login>.
+
+=cut
+
 template login_widget => sub {
 
     my ( $action, $next ) = get( 'action', 'next' );
@@ -70,9 +97,16 @@
     }
 };
 
-template 'let/reset_lost_password' => page {
+=head2 let/reset_lost_password
+
+After requesting a password reset and clicking on the link sent by email, this receives that click and provides the form for resetting the password.
+
+See L<Jifty::Plugin::Authentication::Action::ResetLostPassword>.
+
+=cut
+
+template 'let/reset_lost_password' => page { title => 'Reset lost password' } content {
     my ( $next ) = get(qw(next));
-    title is 'Reset lost password' ;
     my $action = Jifty->web->new_action( class => 'ResetLostPassword' );
 
     Jifty->web->form->start( call => $next );
@@ -81,19 +115,34 @@
     Jifty->web->form->end();
 };
 
+=head2 let/confirm_email
+
+Handles the work of confirming an email address for a new account.
+
+See L<Jifty::Plugin::Authenticaiton::Password::View>.
+
+=cut
+
 template 'let/confirm_email' => sub {
     new_action( class => 'ConfirmEmail' )->run;
     redirect("/");
 };
 
-template 'lost_password' => page {
+=head2 lost_password
+
+Starts the process of sending a link to reset a lost password by email.
+
+See L<Jifty::Plugin::Authentication::Password::SendPasswordReminder>.
+
+=cut
+
+template 'lost_password' => page { title => 'Send a link to reset your password' } content {
     my ( $next ) = get(qw(next));
     my $action = Jifty->web->new_action(
         moniker => 'password_reminder',
         class   => 'SendPasswordReminder',
     );
 
-    title is _('Send a link to reset your password');
     outs( _(  "You lost your password. A link to reset it will be sent to the following email address:"));
     my $focused = 0;
     Jifty->web->form->start( call => $next );
@@ -103,9 +152,22 @@
 
 };
 
-template 'passwordreminder' => page {
+=head2 passwordreminder
+
+Starts the process of sending a link to reset a lost password by email.
+
+See L<Jifty::Plugin::Authentication::Password::SendPasswordReminder>.
+
+=begin comment
+
+What's the difference between lost_password and passwordreminder? -- Sterling
+
+=end comment
+
+=cut
+
+template 'passwordreminder' => page { title => 'Send a password reminder' } content {
     my $next = get('next');
-     title is  _('Send a password reminder');
     my $action = Jifty->web->new_action(
         moniker => 'password_reminder',
         class   => 'SendPasswordReminder',
@@ -119,4 +181,52 @@
     Jifty->web->form->end();
 };
 
+=head2 resend_confirmation
+
+Request a new email confirmation message be sent to your email account.
+
+See L<Jifty::Plugin::Authentication::Password::Action::ResendConfirmation>.
+
+=cut
+
+template 'resend_confirmation' => page { title => 'Resend Confirmation Email' } content {
+    my $resend = Jifty->web->new_action(
+        class   => 'ResendConfirmation',
+        moniker => 'resendconf'
+    );
+
+    if (    Jifty->web->current_user->id
+        and Jifty->web->current_user->user_object->email_confirmed )
+    {
+        Jifty->web->redirect('/');
+    } else {
+        div {
+            attr { id => 'overview' };
+            form {
+                Jifty->web->form->next_page( url => '/' );
+
+                p {
+                    _(  q{Fill in your address below, and we'll send out another confirmation email to you. }
+                    );
+                    render_param( $resend => 'email', focus => 1 );
+                    form_submit( label => 'Resend Confirmation' );
+                    }
+                }
+            }
+
+    }
+};
+
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Authentication::Password>, L<Jifty::Plugin::Authentication::Password::Dispatcher>
+
+=head1 LICENSE
+
+Jifty is Copyright 2005-2007 Best Practical Solutions, LLC.
+Jifty is distributed under the same terms as Perl itself.
+
+=cut
+
+
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/CompressedCSSandJS.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/CompressedCSSandJS.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/CompressedCSSandJS.pm	Sun Jul 22 21:13:55 2007
@@ -2,20 +2,181 @@
 use warnings;
 
 package Jifty::Plugin::CompressedCSSandJS;
-use base qw/Jifty::Plugin/;
+use base qw/Jifty::Plugin Class::Accessor::Fast/;
 
-# Your plugin goes here.  If takes any configuration or arguments, you
-# probably want to override L<Jifty::Plugin/init>.
+use Digest::MD5 qw(md5_hex);
+use IPC::Run3 'run3';
+use IO::Handle ();
 
 =head1 NAME
 
 Jifty::Plugin::CompressedCSSandJS
 
+=head1 SYNOPSIS
+
+# In your jifty config.yml under the framework section:
+
+  Plugins:
+    - CompressedCSSandJS:
+        js: 1
+        css: 1
+        jsmin: /path/to/jsmin
+
 =head1 DESCRIPTION
 
-This plugin provides auto-compilation and on-wire compression of your application's CSS and Javascript. It is enabled by default.
+This plugin provides auto-compilation and on-wire compression of your
+application's CSS and Javascript. It is enabled by default, unless
+your C<ConfigFileVersion> is greater or equal than 2.
+
+It also supports js minifier, you will need to specify the full path.
+The jsmin can be obtained from
+L<http://www.crockford.com/javascript/jsmin.html>.
+
+Note that you will need to use C<ConfigFileVersion> 2 to be able to
+configure jsmin feature.
+
+=cut
+
+__PACKAGE__->mk_accessors(qw(css js jsmin cached_javascript cached_javascript_digest cached_javascript_time ));
+
+=head2 init
+
+Initializes the compression object. Takes a paramhash containing keys
+'css' and 'js' which can be used to disable compression on files of
+that type.
+
+=cut
+
+sub init {
+    my $self = shift;
+    my %opt  = @_;
+    $self->css( $opt{css} );
+    $self->js( $opt{js} );
+    $self->jsmin( $opt{jsmin} );
+
+    Jifty::Web->add_trigger(
+        name      => 'include_javascript',
+        callback  => sub { $self->_include_javascript(@_) },
+        abortable => 1,
+    ) if $self->js_enabled;
+}
+
+=head2 js_enabled
+
+Returns whether JS compression is enabled (which it is by default)
+
+=cut
+
+sub js_enabled {
+    my $self = shift;
+    defined $self->js ? $self->js : 1;
+}
+
+=head2 css_enabled
+
+Returns whether CSS compression is enabled (which it is by default)
+
+=cut
+
+sub css_enabled {
+    my $self = shift;
+    defined $self->css ? $self->css : 1;
+}
+
+sub _include_javascript {
+    my $self = shift;
+
+    $self->_generate_javascript;
+    Jifty->web->out( qq[<script type="text/javascript" src="/__jifty/js/]
+            . $self->cached_javascript_digest
+            . qq[.js"></script>] );
+    return 0;
+}
+
+=head3 _generate_javascript
+
+Checks if the compressed JS is generated, and if it isn't, generates
+and caches it.
 
 =cut
 
+sub _generate_javascript {
+    my $self = shift;
+
+    if ( not defined $self->cached_javascript_digest
+        or Jifty->config->framework('DevelMode') ) {
+        Jifty->log->debug("Generating JS...");
+
+        my @roots = map { Jifty::Util->absolute_path( File::Spec->catdir( $_, 'js' ) ) }
+                        Jifty->handler->view('Jifty::View::Static::Handler')->roots;
+
+        my $js = "";
+
+        for my $file ( @{ Jifty::Web->javascript_libs } ) {
+            my $include;
+
+            for my $root (@roots) {
+                my @spec = File::Spec->splitpath( $root, 1 );
+                my $path = File::Spec->catpath( @spec[ 0, 1 ], $file );
+
+                if ( -e $path ) {
+                    $include = $path;
+                    last;
+                }
+            }
+
+            if ( defined $include ) {
+                my $fh;
+
+                if ( open $fh, '<', $include ) {
+                    $js .= "/* Including '$file' */\n\n";
+                    $js .= $_ while <$fh>;
+                    $js .= "\n/* End of '$file' */\n\n";
+                } else {
+                    $js .= "\n/* Unable to open '$file': $! */\n";
+                }
+            } else {
+                $js .= "\n/* Unable to find '$file' */\n";
+            }
+        }
+        if ($self->jsmin) {
+            eval { $self->minify_js(\$js) };
+            Jifty->log->error("Unable to run jsmin: $@") if $@;
+        }
+        $self->cached_javascript($js);
+        $self->cached_javascript_digest( md5_hex($js) );
+        $self->cached_javascript_time(time);
+    }
+}
+
+=head2 minify_js \$js
+
+Runs the given JS through jsmin
+
+=cut
+
+sub minify_js {
+    my $self = shift;
+    my $input = shift;
+    my $output;
+
+    Jifty->log->debug("Minifying JS...");
+
+    # We need to reopen stdout temporarily, because in FCGI
+    # environment, stdout is tied to FCGI::Stream, and the child
+    # of the run3 wouldn't be able to reopen STDOUT properly.
+    my $stdout = IO::Handle->new;
+    $stdout->fdopen( 1, 'w' );
+    local *STDOUT = $stdout;
+
+    my $stderr = IO::Handle->new;
+    $stderr->fdopen( 2, 'w' );
+    local *STDERR = $stderr;
+
+    local $SIG{'CHLD'} = 'DEFAULT';
+    run3 [$self->jsmin], $input, \$output, undef;
+
+    $$input = $output;
+}
 
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/CompressedCSSandJS/Dispatcher.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/CompressedCSSandJS/Dispatcher.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/CompressedCSSandJS/Dispatcher.pm	Sun Jul 22 21:13:55 2007
@@ -13,13 +13,13 @@
 which serve out compiled and compressed CSS and Javascript rules.
 
 =cut
-
+use Compress::Zlib qw();
+use HTTP::Date ();
 
 use Jifty::Dispatcher -base;
 
 on '/__jifty/js/*' => run {
     my $arg = $1;
-    warn "My arg is $arg";
     if ( $arg !~ /^[0-9a-f]{32}\.js$/ ) {
 
         # This doesn't look like a real request for squished JS,
@@ -27,12 +27,13 @@
         Jifty->web->redirect( "/static/js/" . $arg );
     }
 
-    Jifty->web->generate_javascript;
+    my ($ccjs) = Jifty->find_plugin('Jifty::Plugin::CompressedCSSandJS')
+        or Jifty->web->redirect( "/static/js/" . $arg );
 
-    use HTTP::Date ();
+    $ccjs->_generate_javascript;
 
     if ( Jifty->handler->cgi->http('If-Modified-Since')
-        and $arg eq Jifty->web->cached_javascript_digest . '.js' )
+        and $arg eq $ccjs->cached_javascript_digest . '.js' )
     {
         Jifty->log->debug("Returning 304 for cached javascript");
         Jifty->handler->apache->header_out( Status => 304 );
@@ -46,25 +47,22 @@
     # XXX TODO: If we start caching the squished JS in a file somewhere, we
     # can have the static handler serve it, which would take care of gzipping
     # for us.
-    use Compress::Zlib qw();
-
     if ( Jifty::View::Static::Handler->client_accepts_gzipped_content ) {
         Jifty->log->debug("Sending gzipped squished JS");
         Jifty->handler->apache->header_out( "Content-Encoding" => "gzip" );
         Jifty->handler->apache->send_http_header();
         binmode STDOUT;
-        print Compress::Zlib::memGzip( Jifty->web->cached_javascript );
+        print Compress::Zlib::memGzip( $ccjs->cached_javascript );
     } else {
         Jifty->log->debug("Sending squished JS");
         Jifty->handler->apache->send_http_header();
-        print Jifty->web->cached_javascript;
+        print $ccjs->cached_javascript;
     }
     abort;
 };
 
 on '/__jifty/css/*' => run {
     my $arg = $1;
-    warn "My arg is $arg";
     if ( $arg !~ /^[0-9a-f]{32}\.css$/ ) {
 
         # This doesn't look like a real request for squished CSS,
@@ -74,8 +72,6 @@
 
     Jifty->web->generate_css;
 
-    use HTTP::Date ();
-
     if ( Jifty->handler->cgi->http('If-Modified-Since')
         and $arg eq Jifty->web->cached_css_digest . '.css' )
     {
@@ -90,8 +86,6 @@
     # XXX TODO: If we start caching the squished CSS in a file somewhere, we
     # can have the static handler serve it, which would take care of gzipping
     # for us.
-    use Compress::Zlib qw();
-
     if ( Jifty::View::Static::Handler->client_accepts_gzipped_content ) {
         Jifty->log->debug("Sending gzipped squished CSS");
         Jifty->handler->apache->header_out( "Content-Encoding" => "gzip" );
@@ -105,4 +99,5 @@
     }
     abort;
 };
+
 1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Debug.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Debug.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,17 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Debug;
+use base qw/Jifty::Plugin/;
+
+=head1 NAME
+
+Jifty::Plugin::Debug - a plugin to log each incoming request
+
+=head1 DESCRIPTION
+
+Enable this plugin in your F<etc/config.yml> (requires no configuration) and the plugin add an INFO level log message on each request received. It will contain the PID of the current process, the URL requested, and the username (if any) of the person making the request.
+
+=cut
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Debug/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Debug/Dispatcher.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,28 @@
+use warnings;
+use strict;
+
+package Jifty::Plugin::Debug::Dispatcher;
+use Jifty::Dispatcher -base;
+
+=head1 NAME
+
+Jifty::Plugin::Debug::Dispatcher - dispatcher for the debug plugin
+
+=head1 DESCRIPTION
+
+This adds a debugging rule to record debugging information about every request.
+
+=head1 RULES
+
+=head2 on qr'(.*)'
+
+Records the request. The INFO level log message recorded contains the PID of the current process, the URL requested, and the username (if any) attached to the current session.
+
+=cut
+
+on qr'(.*)' => run {
+    Jifty->log->info("[$$] $1 ".(Jifty->web->current_user->id ? Jifty->web->current_user->username : ''));
+};
+
+1;
+

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/ErrorTemplates/View.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/ErrorTemplates/View.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/ErrorTemplates/View.pm	Sun Jul 22 21:13:55 2007
@@ -55,7 +55,7 @@
 {
     no warnings qw'redefine';
 
-    sub wrapper ($) {
+    sub wrapper {
         my $code = shift;
         html {
             head {

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Feedback.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Feedback.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,48 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Feedback;
+use base qw/Jifty::Plugin Class::Accessor/;
+
+# Your plugin goes here.  If takes any configuration or arguments, you
+# probably want to override L<Jifty::Plugin/init>.
+
+=head1 NAME
+
+Jifty::Plugin::Feedback
+
+=head1 DESCRIPTION
+
+This plugin provides a "feedback box" for your app.
+
+
+Add to your app's config:
+
+  Plugins: 
+    - Feedback: 
+        from: defaultsender at example.com
+        to: recipient at example.com
+
+Add to your app's UI where you want the feedback box:
+
+ show '/feedback/request_feedback';
+
+
+=cut
+
+__PACKAGE__->mk_accessors(qw(from to));
+
+=head2 init
+
+Initializes the Feedback object. Takes a paramhash with keys 'from' and 'to', which are email addresses.
+
+=cut
+
+sub init {
+    my $self = shift;
+    my %opt = @_;
+    $self->from($opt{'from'});
+    $self->to($opt{'to'});
+}
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Feedback/Action/SendFeedback.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Feedback/Action/SendFeedback.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,95 @@
+
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Plugin::Feedback::Action::SendFeedback
+
+=cut
+
+package Jifty::Plugin::Feedback::Action::SendFeedback;
+use base qw/Jifty::Action/;
+
+
+=head2 arguments
+
+The fields for C<SendFeedback> are:
+
+=over 4
+
+=item content: a big box where the user can type in what eits them
+
+
+=back
+
+=cut
+
+sub arguments {
+        {
+            content => {
+                    label   => '',
+                    render_as => 'Textarea',
+                    rows => 5,
+                    cols => 60,
+                    sticky => 0
+            },
+        }
+
+}
+
+=head2 take_action
+
+Send some mail to the hiveminders describing the issue.
+
+=cut
+
+sub take_action {
+    my $self = shift;
+    return 1 unless ( $self->argument_value('content') );
+
+    my ($plugin) = Jifty->find_plugin('Jifty::Plugin::Feedback');
+    my $debug_info = $self->build_debugging_info();
+
+    my $msg = $self->argument_value('content') . "\n\n" . $debug_info;
+    my $subject = substr( $self->argument_value('content'), 0, 60 );
+    $subject =~ s/\n/ /g;
+
+    # Fall back to normal email
+    my $mail = Jifty::Notification->new;
+    $mail->body($msg);
+    $mail->from(
+        (          Jifty->web->current_user->id
+                && Jifty->web->current_user->user_object->can('email')
+        )
+        ? Jifty->web->current_user->user_object->email()
+        : $plugin->from
+    );
+    $mail->recipients( $plugin->to );
+    $mail->subject( "["
+            . Jifty->config->framework('ApplicationName')
+            . " feedback] "
+            . $subject );
+    $mail->send_one_message;
+
+    $self->result->message(qq[Thanks for the feedback. We appreciate it!]);
+    return 1;
+}
+
+=head2 build_debugging_info
+
+Strings together the current environment to attach to outgoing
+email. Returns it as a scalar.
+
+=cut
+
+sub build_debugging_info {
+    my $self = shift;
+    my $message = "-- \nPrivate debugging information:\n";
+    $message   .= " $_: $ENV{$_}\n"
+      for sort grep {/^(HTTP|REMOTE|REQUEST)_/} keys %ENV;
+
+    return $message;
+}
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Feedback/View.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Feedback/View.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,61 @@
+use warnings;
+use strict;
+package Jifty::Plugin::Feedback::View;
+
+use Jifty::View::Declare -base;
+
+=head1 NAME
+
+Jifty::Plugin::Feedback::View
+
+=head1 DESCRIPTION
+
+Provides the feedback regions for L<Jifty::Plugin::Feedback>
+
+=cut
+
+template 'feedback/request_feedback' => sub {
+    div {
+        attr { id => 'feedback_wrapper' };
+
+        h3 { _('Send us feedback!') } p {
+            _("Tell us what's good, what's bad, and what else you want %1 to do!",
+	      Jifty->config->framework('ApplicationName'));
+        };
+        render_region(
+            'feedback',
+            path     => "/feedback/region",
+            defaults => {}
+        );
+    };
+};
+
+
+template 'feedback/region' => sub {
+    my $feedback = Jifty->web->new_action(
+        class   => "SendFeedback",
+        moniker => "feedback"
+    );
+
+    if ( Jifty->web->response->result("feedback")) { 
+    span {
+        attr { id => 'feedback-result' };
+        Jifty->web->response->result("feedback")->{'message'};
+    };
+    };
+    div {
+        attr { id => 'feedback' };
+
+        form {
+            render_param( $feedback => 'content' );
+            form_submit(
+                label   => "Send",
+                onclick => {
+                    submit       => $feedback,
+                    refresh_self => 1
+                }
+            );
+            }
+        }
+};
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/GoogleMap.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/GoogleMap.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,76 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::GoogleMap;
+use base qw/Jifty::Plugin Class::Accessor::Fast/;
+
+
+=head1 NAME
+
+Jifty::Plugin::GoogleMap
+
+=head1 SYNOPSIS
+
+# In your jifty config.yml under the framework section:
+
+  Plugins:
+    - GoogleMap:
+        apikey: ABQIAAAA66LEkTHjdh-UhDZ_NkfdjBTb-vLQlFZmc2N8bgWI8YDPp5FEVBTjCfxPSocuJ53SPMNQDO7Sywpp_w
+
+# note that this is an api for http://localhost:8888/
+
+
+In your model class schema description, add the following:
+
+    column location => is GeoLocation;
+
+
+=head1 DESCRIPTION
+
+This plugin provides a Google-map widget for Jifty, as well as a new GeoLocation column type.
+
+
+=cut
+
+__PACKAGE__->mk_accessors(qw(apikey));
+
+=head2 init
+
+=cut
+
+sub init {
+    my $self = shift;
+    my %opt  = @_;
+    $self->apikey( $opt{apikey} );
+    Jifty->web->add_external_javascript("http://maps.google.com/maps?file=api&v=2&key=".$self->apikey);
+    Jifty->web->add_javascript(qw( google_map.js ) );
+    Jifty->web->add_css('google_map.css');
+}
+
+sub _geolocation {
+    my ($column, $from) = @_;
+    my $name = $column->name;
+    $column->virtual(1);
+    $column->container(1);
+    for (qw(x y)) {
+        Jifty::DBI::Schema::_init_column_for(
+            Jifty::DBI::Column->new({ type => 'double precision',
+                                      name => $name."_$_",
+                                      render_as => 'hidden',
+                                      writable => $column->writable,
+                                      readable => $column->readable }),
+            $from);
+    }
+    no strict 'refs';
+    *{$from.'::'.$name} = sub { return { map { my $method = "${name}_$_"; $_ => $_[0]->$method } qw(x y) } };
+    *{$from.'::'.'set_'.$name} = sub { die "not yet" };
+}
+
+use Jifty::DBI::Schema;
+Jifty::DBI::Schema->register_types(
+    GeoLocation =>
+        sub { _init_handler is \&_geolocation, render_as 'Jifty::Plugin::GoogleMap::Widget' },
+);
+
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/GoogleMap/Widget.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/GoogleMap/Widget.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,78 @@
+use warnings;
+use strict;
+ 
+package Jifty::Plugin::GoogleMap::Widget;
+
+use base qw/Jifty::Web::Form::Field/;
+
+=head1 NAME
+
+Jifty::Plugin::GoogleMap::Widget - google map widget for geolocation display and editing
+
+=head1 METHODS
+
+
+=cut
+
+sub accessors { shift->SUPER::accessors() };
+
+=head2 render_widget
+
+Renders form fields as googlemap widget.
+
+=cut
+
+# XXX: doesn't work
+#use Template::Declare;
+#use Template::Declare::Tags;
+
+sub render_widget {
+    my $self = shift;
+    my $readonly = shift;
+    my $action = $self->action;
+    $readonly = $readonly ? 1 : 0;
+
+    my ($x, $y) = map { $action->form_field($self->name . "_$_")->current_value } qw( x y );
+    my ($xid, $yid) = map { $action->form_field($self->name . "_$_")->element_id } qw( x y );
+    my $use_default = defined $x ? 0 : 1;
+    ($x, $y) = (-71.2, 42.4) if $use_default;
+    my $zoom_level = $use_default ? 1 : 13;
+    my $element_id = $self->element_id;
+    Jifty->web->out(qq{<div class="googlemap-widget-wrapper" style="width: 250px; height: 250px"><div @{[$self->_widget_class]} id="$element_id" style="width: 250px; height: 250px"></div>});
+    Jifty->web->out(qq{<div class="googlemap-search-results" id="$element_id-result"></div></div>});
+    Jifty->web->out(qq{<script type="text/javascript">
+Jifty.GMap.location_editor( \$("$element_id"), $x, $y, "$xid", "$yid", $zoom_level, $use_default, $readonly);
+</script>
+});
+
+
+    return '';
+    Template::Declare->new_buffer_frame;
+
+    div { { id is $self->element_id, style is "width: 200px; height: 200px" } };
+    outs('hi');
+    script { { type is "text/javascript" };
+      qq{if (GBrowserIsCompatible()) {
+         var map = new GMap2(document.getElementById("@{[$self->element_id]}"));
+         map.setCenter(new GLatLng(37.4419, -122.1419), 13);
+      }}
+    };
+
+warn "-----------_".Template::Declare->buffer->data;
+    Jifty->web->out(Template::Declare->buffer->data);
+    Template::Declare->end_buffer_frame;
+    return '';
+}
+
+=head2 render_value
+
+Renders value as a checkbox widget.
+
+=cut
+
+sub render_value {
+    $_[0]->render_widget('readonly');
+    return '';
+}
+
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID.pm	Sun Jul 22 21:13:55 2007
@@ -4,4 +4,14 @@
 package Jifty::Plugin::OpenID;
 use base qw/Jifty::Plugin/;
 
+=head1 NAME
+
+Jifty::Plugin::OpenID
+
+=head1 DESCRIPTION
+
+Provides OpenID authentication for your app
+
+=cut
+
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Action/CreateOpenIDUser.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Action/CreateOpenIDUser.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Action/CreateOpenIDUser.pm	Sun Jul 22 21:13:55 2007
@@ -10,6 +10,12 @@
 package Jifty::Plugin::OpenID::Action::CreateOpenIDUser;
 use base qw/Jifty::Action::Record/;
 
+=head2 record_class 
+
+Returns the record class for this action
+
+=cut
+
 sub record_class {
     Jifty->app_class("Model", "User")
 }
@@ -95,7 +101,7 @@
 sub report_success {
     my $self = shift;
     # Your success message here
-    $self->result->message( _("Welcome, ") . Jifty->web->current_user->user_object->name . "." );
+    $self->result->message( _("Welcome, ") . Jifty->web->current_user->username . "." );
 }
 
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Dispatcher.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Dispatcher.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Dispatcher.pm	Sun Jul 22 21:13:55 2007
@@ -4,6 +4,16 @@
 package Jifty::Plugin::OpenID::Dispatcher;
 use Jifty::Dispatcher -base;
 
+=head1 NAME
+
+Jifty::Plugin::OpenID::Dispatcher
+
+=head1 DESCRIPTION
+
+Dispatcher for L<Jifty::Plugin::OpenID>.  Handles a lot of the work.
+
+=cut
+
 before qr'^/(?:openid/link)' => run {
     tangent('/openid/login') unless (Jifty->web->current_user->id)
 };

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Mixin/Model/User.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/Mixin/Model/User.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,101 @@
+package Jifty::Plugin::OpenID::Mixin::Model::User;
+use strict;
+use warnings;
+use Jifty::DBI::Schema;
+use base 'Jifty::DBI::Record::Plugin';
+use URI;
+
+=head1 NAME
+
+Jifty::Plugin::OpenID::Mixin::Model::User
+
+=head1 DESCRIPTION
+
+L<Jifty::Plugin::OpenID> mixin for the User model.  Provides an 'openid' column.
+
+=cut
+
+use Jifty::Plugin::OpenID::Record schema {
+
+our @EXPORT = qw(has_alternative_auth link_to_openid);
+
+column openid =>
+  type is 'text',
+  label is 'OpenID',
+  hints is q{You can use your OpenID to log in quickly and easily.},
+  is distinct,
+  is immutable;
+
+};
+
+=head2 has_alternative_auth
+
+=cut
+
+sub has_alternative_auth { 1 }
+
+=head2 register_triggers
+
+=cut
+
+sub register_triggers {
+    my $self = shift;
+    $self->add_trigger(name => 'validate_openid', callback => \&validate_openid, abortable => 1);
+    $self->add_trigger(name => 'canonicalize_openid', callback => \&canonicalize_openid);
+}
+
+=head2 validate_openid
+
+=cut
+
+sub validate_openid {
+    my $self   = shift;
+    my $openid = shift;
+
+    my $uri = URI->new( $openid );
+
+    return ( 0, q{That doesn't look like an OpenID URL.} )
+        if not defined $uri;
+
+    my $temp_user = Jifty->app_class("Model", "User")->new;
+    $temp_user->load_by_cols( openid => $uri->canonical );
+
+    # It's ok if *we* have the openid we're looking for
+    return ( 0, q{It looks like somebody else has claimed that OpenID.} )
+        if $temp_user->id and ( not $self->id or $temp_user->id != $self->id );
+
+    return 1;
+}
+
+=head2 canonicalize_openid
+
+=cut
+
+sub canonicalize_openid {
+    my $self   = shift;
+    my $openid = shift;
+
+    return ''
+        if not defined $openid or not length $openid;
+
+    $openid = 'http://' . $openid
+        if $openid !~ m{^http://};
+
+    my $uri = URI->new( $openid );
+
+    return $uri->canonical;
+}
+
+=head2 link_to_openid
+
+Links User's account to the specified OpenID (bypassing ACLs)
+
+=cut
+
+sub link_to_openid {
+    my $self   = shift;
+    my $openid = shift;
+    $self->__set( column => 'openid', value => $openid );
+}
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/View.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/OpenID/View.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,70 @@
+package Jifty::Plugin::OpenID::View;
+use strict;
+use warnings;
+use Jifty::View::Declare -base;
+
+=head1 NAME
+
+Jifty::Plugin::OpenID::View
+
+=head1 DESCRIPTION
+
+The view class for L<Jifty::Plugin::OpenID>.  Provides login and create pages.
+
+=cut
+
+template 'openid/login' => page {
+    { title is _("Login with your OpenID") }
+    my ($action, $next) = get('action', 'next');
+
+    div {
+        unless ( Jifty->web->current_user->id ) {
+            div {
+                attr { id => 'openid-login' };
+                outs(
+                    p {
+                        em {
+                            _(  qq{If you have a Livejournal or other OpenID account, you don\'t even need to sign up. Just log in.}
+                            );
+                        }
+                    }
+                );
+                Jifty->web->form->start( call => $next );
+                render_action($action);
+                form_submit(
+                    label  => _("Go for it!"),
+                    submit => $action
+                );
+                Jifty->web->form->end;
+            };
+        }
+        else {
+            outs( _("You already logged in.") );
+        }
+    }
+};
+
+template 'openid/create' => page {
+    title is 'Set your username';
+    my ( $action, $next ) = get( 'action', 'next' );
+
+    p {
+        outs(
+            _(  'We need you to set a username or quickly check the one associated with your OpenID. Your username is what other people will see when you ask questions or make suggestions'
+            )
+        );
+    };
+    p {
+        outs(
+            _(  'If the username provided conflicts with an existing username or contains invalid characters, you will have to give us a new one.'
+            )
+        );
+    };
+    Jifty->web->form->start( call => $next );
+    render_param( $action, 'name', default_value => get('nickname') );
+    form_submit( label => _('Continue'), submit => $action );
+    Jifty->web->form->end;
+};
+
+
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/REST/Dispatcher.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/REST/Dispatcher.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/REST/Dispatcher.pm	Sun Jul 22 21:13:55 2007
@@ -155,9 +155,12 @@
     my $record = shift;
     # We could use ->as_hash but this method avoids transforming refers_to
     # columns into JDBI objects
+
+    # XXX: maybe just test ->virtual?
     my %data   = map {
                     $_ => (UNIVERSAL::isa( $record->column( $_ )->refers_to,
-                                           'Jifty::DBI::Collection' )
+                                           'Jifty::DBI::Collection' ) ||
+                           $record->column($_)->container
                              ? undef
                              : stringify( $record->_value( $_ ) ) )
                  } $record->readable_attributes;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/SinglePage.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/SinglePage.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,73 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::SinglePage;
+use base qw/Jifty::Plugin Class::Accessor/;
+
+__PACKAGE__->mk_accessors(qw(region_name));
+
+=head1 NAME
+
+Jifty::Plugin::SinglePage
+
+=head1 DESCRIPTION
+
+Makes your normal Jifty app into a single-page app through clever use of regions
+
+=head2 init
+
+Registers a before_new trigger to modify links and sets up the special region
+
+=cut
+
+sub init {
+    my $self = shift;
+    Jifty::Web::Form::Clickable->add_trigger( before_new => _sp_link($self));
+    my %opt = @_;
+    $self->region_name($opt{region_name} || '__page');
+}
+
+sub _push_onclick {
+    my $self = shift;
+    my $args = shift;
+    $args->{onclick} = [ $args->{onclick} ? $args->{onclick} : () ]
+        unless ref $args->{onclick} eq 'ARRAY';
+    push @{$args->{onclick}}, @_ if @_;
+}
+
+sub _sp_link {
+    my $self = shift;
+    return sub {
+        my ( $clickable, $args ) = @_;
+        my $url = $args->{'url'};
+        if ( $url && $url !~ m/^#/ && $url !~ m{^https?://} ) {
+            $self->_push_onclick($args, {
+                region       => $self->region_name,
+                replace_with => $url,
+                args         => $args->{parameters}});
+        }
+        elsif (exists $args->{submit}) {
+            $self->_push_onclick($args, { refresh_self => 1, submit => $args->{submit} });
+            $args->{as_button} = 1;
+        }
+        if (my $form = delete $args->{_form}) {
+            $args->{call} = $form->call;
+        }
+        my $onclick = $args->{onclick};
+        if ( $args->{onclick} ) {
+            $self->_push_onclick($args);    # make sure it's array
+            for my $onclick ( @{ $args->{onclick} } ) {
+                next unless UNIVERSAL::isa($onclick, 'HASH');
+                if ( $onclick->{region} && !ref( $onclick->{region} ) ) {
+                    my $region = $self->region_name;
+                    $onclick->{region} = $region . '-' . $onclick->{region}
+                        unless $onclick->{region} eq $region
+                        or $onclick->{region} =~ m/^\Q$region\E-/;
+                }
+            }
+        }
+    }
+}
+
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/SinglePage/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/SinglePage/Dispatcher.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,40 @@
+package Jifty::Plugin::SinglePage::Dispatcher;
+use strict;
+use warnings;
+use Jifty::Dispatcher -base;
+
+=head1 NAME
+
+Jifty::Plugin::SinglePage::Dispatcher
+
+=head1 DESCRIPTION
+
+Dispatcher for L<Jifty::Plugin::SinglePage>
+
+=cut
+
+before '__jifty/webservices/*' => run {
+    my (@actions) = grep { $_->class eq 'Jifty::Action::Redirect' } values %{ Jifty->web->request->{'actions'} };
+    $_->active(0) for @actions;
+
+    # XXX: shouldn't have multiple redirect
+    # Simply ignore Redirect from webservice if we are not in SPA
+    set '_webservice_redirect' => [map { $_->arguments->{url} } @actions]
+        if Jifty->find_plugin('Jifty::Plugin::SinglePage');
+
+};
+
+on qr{(__jifty/webservices/.*)} => run {
+    my $actions = get '_webservice_redirect';
+    for my $act (@$actions) {
+        if ($act =~ m{^https?://}) {
+            set '_webservice_external_redirect' => $act;
+        }
+        else {
+            Jifty->web->webservices_redirect($act);
+        }
+    }
+    show $1;
+};
+
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews.pm	Sun Jul 22 21:13:55 2007
@@ -3,5 +3,14 @@
 package Jifty::Plugin::SiteNews;
 use base qw'Jifty::Plugin';
 
+=head1 NAME
+
+Jifty::Plugin::SiteNews
+
+=head1 DESCRIPTION
+
+Provides a way to include site news in your Jifty app
+
+=cut
 
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/Dispatcher.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/Dispatcher.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/Dispatcher.pm	Sun Jul 22 21:13:55 2007
@@ -4,6 +4,15 @@
 package Jifty::Plugin::SiteNews::Dispatcher;
 use base 'Jifty::Dispatcher';
 
+=head1 NAME
+
+Jifty::Plugin::SiteNews::Dispatcher
+
+=head1 DESCRIPTION
+
+Dispatcher for L<Jifty::Plugin::SiteNews>
+
+=cut
 
 
 

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/Mixin/Model/News.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/Mixin/Model/News.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/Mixin/Model/News.pm	Sun Jul 22 21:13:55 2007
@@ -25,6 +25,11 @@
   render_as is 'Textarea';
 };
 
+=head2 create
+
+Create the News model. Takes a paramhash with keys author_id, created, title, and content.
+
+=cut
 
 sub create {
     my $self = shift;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/View/News.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/View/News.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/SiteNews/View/News.pm	Sun Jul 22 21:13:55 2007
@@ -5,12 +5,25 @@
 use Jifty::View::Declare -base;
 use Jifty::View::Declare::CRUD;
 
+=head1 NAME
+
+Jifty::Plugin::SiteNews::View::News
+
+=head1 DESCRIPTION
+
+The /news pages for L<Jifty::Plugin::SiteNews>
+
+=cut
+
 import_templates Jifty::View::Declare::CRUD under '/';
 
-sub object_type { 'News' }
+=head2 object_type
 
-sub fragment_base_path {'/news'}
+News
 
+=cut
+
+sub object_type { 'News' }
 
 template search_region => sub {''};
 
@@ -19,7 +32,7 @@
     form {
             render_region(
                 name     => 'newslist',
-                path     => '/news/list');
+                path     => 'list');
     }
 
 };

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/SkeletonApp/View.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/SkeletonApp/View.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/SkeletonApp/View.pm	Sun Jul 22 21:13:55 2007
@@ -15,7 +15,9 @@
 =head1 DESCRIPTION
 
 This somewhat-finished (But not quite) template library implements
-Jifty's "pony" Application. It could certainly use some refactoring. (And some of the menu stuff should get factored out into a dispatcher or the other plugins that implement it.
+Jifty's "pony" Application. It could certainly use some
+refactoring. (And some of the menu stuff should get factored out into
+a dispatcher or the other plugins that implement it.
 
 
 =cut
@@ -26,9 +28,7 @@
         if (    Jifty->web->current_user->id
             and Jifty->web->current_user->user_object )
         {
-            my $u      = Jifty->web->current_user->user_object;
-            my $method = $u->_brief_description;
-            eval {_( 'Hiya, %1.', $u->$method() )};
+            _( 'Hiya, %1.', Jifty->web->current_user->username );
         }
         else {
             _("You're not currently signed in.");
@@ -69,7 +69,8 @@
 };
 
 private template 'keybindings' => sub {
-    div { id is "keybindings" };
+    div { id is "keybindings";
+      outs_raw('<script type="text/javascript"><!-- Jifty.KeyBindings.reset() --></script>') };
 };
 
 #template 'index.html' => page { { title is _('Welcome to your new Jifty application') } img { src is "/static/images/pony.jpg", alt is _( 'You said you wanted a pony. (Source %1)', 'http://hdl.loc.gov/loc.pnp/cph.3c13461'); }; };

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/TabView/View.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/TabView/View.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,77 @@
+package Jifty::Plugin::TabView::View;
+use strict;
+use warnings;
+
+# XXX: To be converted to a plugin with included css and images.
+
+use Jifty::View::Declare -base;
+
+use base 'Exporter';
+our @EXPORT = qw(render_tabs);
+
+=head1 NAME
+
+Jifty::Plugin::TabView::View - render tabview using yui tabs
+
+=head1 SYNOPSIS
+
+  use Jifty::Plugin::TabView::View;
+  template 'index.html' => page {
+     my $self = shift;
+     $self->render_tabs('foo', [qw(id)], qw( foo bar_tab ) );
+  };
+  template 'foo' => sub { ... };
+  template 'bar' => sub { ... };
+
+=head2 render_tabs
+
+Returns some Template::Declare with tabs rendered with the yui tabs
+If a tab ends in _tab, it means it should contain a stub region to be
+replaced by the corresponding fragment onclick to that tab.
+
+=cut
+
+sub render_tabs {
+    my ($self, $divname, $args, @tabs) = @_;
+
+    outs_raw(qq'<script type="text/javascript">
+	var myTabs = new YAHOO.widget.TabView("$divname");
+	</script>'  );
+
+
+    div { { id is $divname, class is 'yui-navset'}
+	  ul { { class is 'yui-nav'};
+	       my $i = 0;
+	       for (@tabs) {
+		   my $tab = $_;
+		   li { { class is 'selected' unless $i };
+			hyperlink(url => '#tab'.++$i, label => $tab,
+				  $tab =~ s/_tab$// ? 
+				  (onclick =>
+				  { region       => Jifty->web->current_region ? Jifty->web->current_region->qualified_name."-$tab-tab" : "$tab-tab",
+				    replace_with => $self->can('fragment_for') ? $self->fragment_for($tab) : $tab, # XXX: should have higher level function handling mount point
+				    args => { map { $_ => get($_)} @$args },
+				  }) : ()
+				 ) }
+	       }
+	   };
+	  div { {class is 'yui-content' };
+      my $default_shown;
+		for (@tabs) {
+		    div { 
+			if (s/_tab$//) {
+			    render_region(name => $_.'-tab', 
+                          ($default_shown++)? () : ( path => $_, args =>  { map { $_ => get($_)} @$args })
+                          )
+			}
+			else {
+			    die "$self $_" unless $self->has_template($_);
+			    $self->has_template($_)->(); 
+			}
+		    }
+		}
+	    }
+      };
+};
+
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/User.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/User.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/User.pm	Sun Jul 22 21:13:55 2007
@@ -4,18 +4,22 @@
 package Jifty::Plugin::User;
 use base qw/Jifty::Plugin/;
 
-# Your plugin goes here.  If takes any configuration or arguments, you
-# probably want to override L<Jifty::Plugin/init>.
-
 =head1 NAME
 
-Jifty::Plugin::User
+Jifty::Plugin::User - plugin for building user models
 
 =head1 DESCRIPTION
 
 This plugin provides a "user" mixin for your application's user model class.
 
-See L<Jifty::Plugin::User/> for more details.
+=head1 SEE ALSO
+
+L<Jifty::Manual::AccessControl>, L<Jifty::Plugin::User::Mixin::Model::User>, L<Jifty::Plugin::Authentication::Password>
+
+=head1 LICENSE
+
+Jifty is Copyright 2005-2007 Best Practical Solutions, LLC.
+Jifty is distributed under the same terms as Perl itself.
 
 =cut
 

Modified: jifty/branches/autoversioning/lib/Jifty/Plugin/User/Mixin/Model/User.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Plugin/User/Mixin/Model/User.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/User/Mixin/Model/User.pm	Sun Jul 22 21:13:55 2007
@@ -7,9 +7,9 @@
 
 =head1 NAME
 
-Jifty::Plugin::User::Mixin::Model::User
+Jifty::Plugin::User::Mixin::Model::User - user model base mixin
 
-=head1 DESCRIPTION
+=head1 SYNOPSIS
 
  package MyApp::Model::User;
  use Jifty::DBI::Schema;
@@ -18,8 +18,27 @@
  };
  
  use Jifty::Plugin::User::Mixin::Model::User; # Imports two columns: name and email
- 
 
+=head1 DESCRIPTION
+
+This mixin may be added to a model to give your user accounts a name and an email address. This module may be used as the basic building block for building account models in your application. It can be combined with mixins from an authentication plugin to create an object suitable for a given authentication mechanism.
+
+=head1 SCHEMA
+
+This mixin model adds the following columns to the model.
+
+=head2 name
+
+This is the username/nickname for the user of the account.
+
+=head2 email
+
+This is the email address of the account. It is intended as a bare minimum confirmation of identity and for communication of password resets and other account information.
+
+=head2 email_confirmed
+
+This is a flag indicating whether the user has confirmed ownership of the given email address.
+ 
 =cut
 
 use base 'Jifty::DBI::Record::Plugin';
@@ -37,9 +56,7 @@
 
 };
 
-# Your model-specific methods go here.
-
-
+=head1 METHODS
 
 =head2 set_email ADDRESS
 
@@ -92,6 +109,16 @@
     return 1;
 }
 
+=head1 SEE ALSO
+
+L<Jifty::Plugin::Authentication::Password>, L<Jifty::Plugin::Authentication::Password::Mixin::Model::User>
+
+=head1 LICENSE
+
+Jifty is Copyright 2005-2007 Best Practical Solutions, LLC.
+Jifty is distributed under the same terms as Perl itself.
+
+=cut
 
 1;
 

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,42 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::Userpic;
+use base qw/Jifty::Plugin Class::Accessor::Fast/;
+
+
+=head1 NAME
+
+Jifty::Plugin::Userpic
+
+=head1 SYNOPSIS
+
+In your model class schema description, add the following:
+
+    column userpic => is Userpic;
+
+
+=head1 DESCRIPTION
+
+This plugin provides user pictures for Jifty;
+
+
+=cut
+
+use Jifty::DBI::Schema;
+
+sub _userpic {
+    my ($column, $from) = @_;
+    my $name = $column->name;
+    $column->type('blob');
+}
+
+use Jifty::DBI::Schema;
+
+Jifty::DBI::Schema->register_types(
+    Userpic =>
+        sub { _init_handler is \&_userpic,  render_as 'Jifty::Plugin::Userpic::Widget'},
+);
+
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic/Dispatcher.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic/Dispatcher.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,23 @@
+package Jifty::Plugin::Userpic::Dispatcher;
+
+use Jifty::Dispatcher -base;
+
+on '/=/plugin/userpic/*/#/*' => run {
+    my $class = $1;
+    my $id = $2;
+    my $field = $3;
+
+    if ($class->isa('Jifty::Record')) {
+
+        my $item = $class->new();
+        $item->load($id);
+
+        if ($item->id) {
+            set item => $item;
+            set field => $field;
+            show '/userpic/image';
+        }
+    }
+};
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic/View.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic/View.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,12 @@
+package Jifty::Plugin::Userpic::View;
+
+use Jifty::View::Declare -base;
+
+template 'userpic/image' => sub {
+    my ($item,$field) = get(qw(item field));
+    Jifty->handler->apache->content_type("image/jpeg");
+    outs_raw($item->$field());
+
+};
+
+1;

Added: jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic/Widget.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/Plugin/Userpic/Widget.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,59 @@
+use warnings;
+use strict;
+ 
+package Jifty::Plugin::Userpic::Widget;
+
+use base qw/Jifty::Web::Form::Field/;
+
+=head1 NAME
+
+Jifty::Plugin::Userpic::Widget - google map widget for geolocation display and editing
+
+=head1 METHODS
+
+
+=cut
+
+sub accessors { shift->SUPER::accessors() };
+
+=head2 render_widget
+
+Renders form fields as googlemap widget.
+
+=cut
+
+sub render_widget {
+    my $self     = shift;
+    my $readonly = shift;
+    my $action   = $self->action;
+    $readonly = $readonly ? 1 : 0;
+
+    if ( $self->current_value ) {
+        Jifty->web->out( qq{<img src="/=/plugin/userpic/}
+                . $self->action->record_class . "/"
+                . $action->record->id . '/'
+                . $self->name
+                . qq{">} );
+    }
+    unless ($readonly) {
+        my $field = qq!<input type="file" name="@{[ $self->input_name ]}" !;
+        $field .= $self->_widget_class();
+        $field .= qq!/>!;
+        Jifty->web->out($field);
+    }
+    '';
+}
+
+
+=head2 render_value
+
+Renders value as a checkbox widget.
+
+=cut
+
+sub render_value {
+    $_[0]->render_widget('readonly');
+    return '';
+}
+
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/Record.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Record.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Record.pm	Sun Jul 22 21:13:55 2007
@@ -152,6 +152,41 @@
     return ($id,$msg);
 }
 
+=head2 _guess_table_name
+
+Guesses a table name based on the class's last part. In addition to the work performed in L<Jifty::DBI::Record>, this method also prefixes the table name with the plugin table prefix, if the model belongs to a plugin.
+
+=cut
+
+sub _guess_table_name {
+    my $self = shift;
+    my $table = $self->SUPER::_guess_table_name;
+
+    # Add plugin table prefix if a plugin model
+    my $class = ref($self) ? ref($self) : $self;
+    my $app_plugin_root = Jifty->app_class('Plugin');
+    if ($class =~ /^(?:Jifty::Plugin::|$app_plugin_root)/) {
+
+        # Guess the plugin class name
+        my $plugin_class = $class;
+        $plugin_class =~ s/::Model::(.*)$//;
+
+        # Try to load that plugin's configuration
+        my ($plugin) = grep { ref $_ eq $plugin_class } Jifty->plugins;
+
+        # Add the prefix if found
+        if (defined $plugin) {
+            $table = $plugin->table_prefix . $table;
+        }
+
+        # Uh oh. Warn, but try to keep going.
+        else {
+            warn "Model $class looks like a plugin model, but $plugin_class could not be found.";
+        }
+    }
+
+    return $table;
+}
 
 =head2 current_user_can RIGHT [ATTRIBUTES]
 
@@ -184,7 +219,7 @@
 
 =back
 
-Models wishing to customize authorization checks should override this method. You you can do so like this:
+Models wishing to customize authorization checks should override this method. You can do so like this:
 
   sub current_user_can {
       my ($self, $right, %args) = @_;
@@ -454,6 +489,18 @@
     $self->SUPER::delete(@_); 
 }
 
+=head2 brief_description
+
+Display the friendly name of the record according to _brief_description.
+
+=cut
+
+sub brief_description {
+    my $self = shift;
+    my $method = $self->_brief_description;
+    return $self->$method;
+}
+
 =head2 _brief_description
 
 When displaying a list of records, Jifty can display a friendly value 
@@ -583,7 +630,7 @@
 
 =head2 add_column_sql column_name
 
-Returns the SQL statement neccessary to add C<column_name> to this class's representation in the database
+Returns the SQL statement necessary to add C<column_name> to this class's representation in the database
 
 =cut
 
@@ -612,7 +659,7 @@
 
 =head2 drop_column_sql column_name
 
-Returns the SQL statement neccessary to remove C<column_name> from this class's representation in the database
+Returns the SQL statement necessary to remove C<column_name> from this class's representation in the database
 
 =cut
 

Modified: jifty/branches/autoversioning/lib/Jifty/Request.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Request.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Request.pm	Sun Jul 22 21:13:55 2007
@@ -221,7 +221,9 @@
     my $self = shift;
     my ($cgi) = @_;
 
-    my $path = $cgi->path_info;
+    # always get the unescaped path for dispatcher, which is already
+    # the case for fastcgi, but not standalone.
+    my $path = URI::Escape::uri_unescape($cgi->path_info);
     $path =~ s/\?.*//;
     $self->path( $path );
 
@@ -511,7 +513,8 @@
     );
 
     # Set us up with the new continuation
-    Jifty->web->_redirect( Jifty->web->url(path => $path)
+    Jifty->web->_redirect( 
+                        $path
                       . ( $path =~ /\?/ ? "&" : "?" ) . "J:C="
                       . $c->id );
 }
@@ -530,8 +533,7 @@
     return if $self->is_subrequest;
     return unless $self->continuation_type and $self->continuation_type eq "call" and $self->continuation;
     $self->log->debug("Calling continuation ".$self->continuation->id);
-    $self->continuation->call;
-    return 1;
+    return $self->continuation->call;
 }
 
 =head2 return_from_continuation

Modified: jifty/branches/autoversioning/lib/Jifty/Request/Mapper.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Request/Mapper.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Request/Mapper.pm	Sun Jul 22 21:13:55 2007
@@ -87,7 +87,11 @@
             for (grep {/^(result(_of)?|argument(_to)?)$/} keys %mapping) {
                 my $action  = $mapping{$_};
                 my $moniker = ref $action ? $action->moniker : $action;
-                my $name = $mapping{name} || $key;
+                # If $key is for an argument of an action, we want to
+                # extract only the argument's name, and not just use
+                # the whole encoded J:A:F-... string.
+                my (undef, $a, undef) = Jifty::Request->parse_form_field_name($key);
+                my $name = $mapping{name} || $a || $key;
 
                 my $type = ($_ =~ /result/) ? "R" : "A";
 
@@ -120,7 +124,7 @@
 
 =item request
 
-The L<Jifty::Request> object to pull action arguments from.  Defauts
+The L<Jifty::Request> object to pull action arguments from.  Defaults
 to the current request.
 
 =item response

Modified: jifty/branches/autoversioning/lib/Jifty/RightsFrom.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/RightsFrom.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/RightsFrom.pm	Sun Jul 22 21:13:55 2007
@@ -3,7 +3,7 @@
 
 =head1 NAME
 
-Jifty::RightsFrom
+Jifty::RightsFrom - Delegate access control to a related object
 
 =head1 SYNOPSIS
 
@@ -23,7 +23,7 @@
 task. L<Jifty::Record/current_user_can> uses this method to make an
 access control decision if it exists.
 
-Note that this means that you a model class can use Jifty::RightsFrom,
+Note that this means that a model class can use Jifty::RightsFrom,
 and still have a custom C<current_user_can> method, and they will not
 interfere with each other.
 

Modified: jifty/branches/autoversioning/lib/Jifty/Schema.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Schema.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Schema.pm	Sun Jul 22 21:13:55 2007
@@ -26,7 +26,11 @@
 
 delete $_SQL_RESERVED{ lc($_) } for (@_SQL_RESERVED_OVERRIDE);
 
+=head2 new
 
+Returns a new Jifty::Schema. Takes no arguments. Will automatically figure out and initialize the models defined in the app's source.
+
+=cut
 
 sub new {
     my $class = shift;
@@ -44,20 +48,27 @@
 =cut
 
 sub _init_model_list {
-
     my $self = shift;
 
+    # Plugins can have models too
+    my @plugins = map { (ref $_).'::Model' } Jifty->plugins;
+
     # This creates a sub "models" which when called, finds packages under
     # the application's ::Model, requires them, and returns a list of their
     # names.
     Jifty::Module::Pluggable->import(
         require     => 1,
         except      => qr/\.#/,
-        search_path => [ "Jifty::Model", Jifty->app_class("Model") ],
+        search_path => [ "Jifty::Model", Jifty->app_class("Model"), @plugins ],
         sub_name    => 'models',
     );
 }
 
+=head2 serialize_current_schema
+
+Returns a serialization of the models in the app
+
+=cut
 
 sub serialize_current_schema {
     my $self = shift;    
@@ -75,7 +86,8 @@
 sub _store_current_schema {
     my $self = shift;
      Jifty::Model::Metadata->store( current_schema      => Jifty::YAML::Dump($self->serialize_current_schema ));
-}
+
+
 
 sub _load_stored_schema {
     my $self = shift;
@@ -85,6 +97,12 @@
 
 
 
+=head2 autoupgrade_schema
+
+Looks at the current schemas as defined by the source and the database and updates the database by adding, dropping, and renaming columns.
+
+=cut
+
 sub autoupgrade_schema {
     my $self = shift;
 
@@ -315,7 +333,11 @@
     return "(" . ( join ", ", @_ ) . ")";
 }
 
+=head2 connect_to_db_for_management
 
+Returns a database handle suitable for direct manipulation.
+
+=cut
 
 sub connect_to_db_for_management {
     my $handle = Jifty::Handle->new();

Modified: jifty/branches/autoversioning/lib/Jifty/Script.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Script.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Script.pm	Sun Jul 22 21:13:55 2007
@@ -2,6 +2,12 @@
 use App::CLI;
 use base qw/App::CLI App::CLI::Command/;
 
+=head1 NAME
+
+Jifty::Script - Base class for all bin/jifty commands
+
+=head1 METHODS
+
 =head2 prepare
 
 C<prepare> figures out which command to run. If the user wants

Modified: jifty/branches/autoversioning/lib/Jifty/Script/App.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Script/App.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Script/App.pm	Sun Jul 22 21:13:55 2007
@@ -147,7 +147,7 @@
 sub _write_config {
     my $self = shift;
     my $cfg = Jifty::Config->new(load_config => 0);
-    my $default_config = $cfg->guess($self->dist_name);
+    my $default_config = $cfg->initial_config($self->dist_name);
     my $file = join("/",$self->prefix, 'etc','config.yml');
     print("Creating configuration file $file\n");
     Jifty::YAML::DumpFile($file => $default_config);

Modified: jifty/branches/autoversioning/lib/Jifty/Script/Deps.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Script/Deps.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Script/Deps.pm	Sun Jul 22 21:13:55 2007
@@ -12,6 +12,12 @@
 use version;
 use Jifty::Config;
 
+=head1 NAME
+
+Jifty::Script::Deps - Looks for module dependencies and attempts to install them from CPAN
+
+=head1 METHODS
+
 =head2 options
 
 Returns a hash of all the options this script takes. (See the usage message for details)

Modified: jifty/branches/autoversioning/lib/Jifty/Script/Plugin.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Script/Plugin.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Script/Plugin.pm	Sun Jul 22 21:13:55 2007
@@ -93,7 +93,7 @@
 package $mod_name;
 use base qw/Jifty::Plugin/;
 
-# Your plugin goes here.  If takes any configuration or arguments, you
+# Your plugin goes here.  If it takes any configuration or arguments, you
 # probably want to override L<Jifty::Plugin/init>.
 
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Script/Schema.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Script/Schema.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Script/Schema.pm	Sun Jul 22 21:13:55 2007
@@ -50,6 +50,7 @@
     } elsif ( $self->{'setup_tables'} ) {
         $self->upgrade_jifty_tables();
         $self->upgrade_application_tables();
+        $self->upgrade_plugin_tables();
     } else {
         print "Done.\n";
     }
@@ -179,11 +180,23 @@
     Jifty::Model::Metadata->store( application_db_version => $appv );
     Jifty::Model::Metadata->store( jifty_db_version       => $jiftyv );
 
+    # For each plugin, update the plugin version
+    for my $plugin (Jifty->plugins) {
+        my $pluginv = version->new( $plugin->version );
+        Jifty::Model::Metadata->store( (ref $plugin).'_db_version' => $pluginv );
+    }
+
     # Load initial data
     eval {
         my $bootstrapper = Jifty->app_class("Bootstrap");
         Jifty::Util->require($bootstrapper);
         $bootstrapper->run() if $bootstrapper->can('run');
+
+        for my $plugin (Jifty->plugins) {
+            my $plugin_bootstrapper = $plugin->bootstrapper;
+            Jifty::Util->require($plugin_bootstrapper);
+            $plugin_bootstrapper->run() if $bootstrapper->can('run');
+        }
     };
     die $@ if $@;
 
@@ -216,20 +229,52 @@
     my $appv = version->new( Jifty->config->framework('Database')->{'Version'} );
     my $jiftyv = version->new( $Jifty::VERSION  );
 
+    my %pluginvs;
+    for my $plugin (Jifty->plugins) {
+        my $plugin_class = ref $plugin;
+        $pluginvs{ $plugin_class } = version->new( $plugin->version );
+    }
 
     for my $model ( @models) {
-       # TODO XXX FIXME:
-       #   This *will* try to generate SQL for abstract base classes you might
-       #   stick in $AC::Model::.
-        if ( $model->can( 'since' ) and ($model =~ /^Jifty::Model::/ ? $jiftyv : $appv) < $model->since ) {
-            $log->info( "Skipping $model, as it should already be in the database");
-            next;
+        # TODO XXX FIXME:
+        #   This *will* try to generate SQL for abstract base classes you might
+        #   stick in $AC::Model::.
+        if ($model->can('since')) {
+            my $app_class   = Jifty->app_class;
+            my $plugin_root = Jifty->app_class('Plugin');
+
+            my $installed_version = 0;
+
+            # Is it a Jifty core model?
+            if ($model =~ /^Jifty::Model::/) {
+                $installed_version = $jiftyv;
+            }
+
+            # Is it a Jifty or application plugin model?
+            elsif ($model =~ /^(?:Jifty::Plugin::|$plugin_root)/) {
+                my $plugin_class = $model;
+                $plugin_class =~ s/::Model::(.*)$//;
+
+                $installed_version = $pluginvs{ $plugin_class };
+            }
+
+            # Otherwise, an application model
+            else {
+                $installed_version = $appv;
+            }
+
+            if ($installed_version < $model->since) {
+                # XXX Is this message correct? 
+                $log->info("Skipping $model, as it should already be in the database");
+                next;
+            }
         }
+
         $log->info("Using $model, as it appears to be new.");
 
-            $self->schema->_check_reserved($model)
+        $self->schema->_check_reserved($model)
         unless ( $self->{'ignore_reserved'}
-            or !Jifty->config->framework('Database')->{'CheckSchema'} );
+                or !Jifty->config->framework('Database')->{'CheckSchema'} );
 
         if ( $self->{'print'} ) {
             print $model->printable_table_schema;
@@ -286,6 +331,29 @@
     }
 }
 
+=head2 upgrade_plugin_tables
+
+Upgrade the tables for each plugin.
+
+=cut
+
+sub upgrade_plugin_tables {
+    my $self   = shift;
+
+    for my $plugin (Jifty->plugins) {
+        my $plugin_class = ref $plugin;
+        my $dbv  = version->new( Jifty::Model::Metadata->load($plugin_class . '_version') || '0.0.1' );
+        my $appv = version->new( $plugin->version );
+
+        return unless $self->upgrade_tables( $plugin_class, $dbv, $appv, $plugin->upgrade_class );
+        if ( $self->{print} ) {
+            warn "Need to upgrade ${plugin_class}_db_version to $appv here!";
+        } else {
+            Jifty::Model::Metadata->store( $plugin_class . '_db_version' => $appv );
+        }
+    }
+}
+
 =head2 upgrade_tables BASECLASS, FROM, TO, [UPGRADECLASS]
 
 Given a C<BASECLASS> to upgrade, and two L<version> objects, C<FROM>

Modified: jifty/branches/autoversioning/lib/Jifty/Script/Server.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Script/Server.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Script/Server.pm	Sun Jul 22 21:13:55 2007
@@ -93,7 +93,6 @@
         if $self->{sigready};
     Log::Log4perl->get_logger($server_class)->less_logging(3)
         if $self->{quiet};
-
     $server_class->new(port => $self->{port})->run;
 }
 

Modified: jifty/branches/autoversioning/lib/Jifty/Server.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Server.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Server.pm	Sun Jul 22 21:13:55 2007
@@ -3,6 +3,10 @@
 
 package Jifty::Server;
 
+=head1 NAME
+
+Jifty::Server - Stand-alone server implementation for Jifty
+
 =head1 SYNOPSIS
 
   use Jifty::Server;
@@ -17,8 +21,7 @@
 =cut
 
 
-use base qw/HTTP::Server::Simple::CGI/;
-use base qw/Jifty::Object/;
+use base qw/HTTP::Server::Simple::CGI Jifty::Object/;
 use File::Spec;
 use Log::Log4perl;
 use HTTP::Server::Simple;

Modified: jifty/branches/autoversioning/lib/Jifty/Subs.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Subs.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Subs.pm	Sun Jul 22 21:13:55 2007
@@ -8,7 +8,7 @@
 
 =head1 NAME
 
-Jifty::Subs - 
+Jifty::Subs - Configure subscriptions for the current window or session
 
 =head1 SYNOPSIS
 
@@ -27,7 +27,7 @@
 
 
 
-=cut
+=head1 METHODS
 
 =head2 add PARAMHASH
 

Modified: jifty/branches/autoversioning/lib/Jifty/Subs/Render.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Subs/Render.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Subs/Render.pm	Sun Jul 22 21:13:55 2007
@@ -4,7 +4,7 @@
 
 =head1 NAME
 
-Jifty::Subs::Render - 
+Jifty::Subs::Render - Helper for subscriptions rendering
 
 =head1 SYNOPSIS
 

Modified: jifty/branches/autoversioning/lib/Jifty/Test.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Test.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Test.pm	Sun Jul 22 21:13:55 2007
@@ -158,9 +158,9 @@
     my $class = shift;
 
     my $test_config = File::Temp->new( UNLINK => 0 );
-    Jifty::YAML::DumpFile($test_config, $class->test_config(Jifty::Config->new));
+    Jifty::YAML::DumpFile("$test_config", $class->test_config(Jifty::Config->new));
     # Invoking bin/jifty and friends will now have the test config ready.
-    $ENV{'JIFTY_TEST_CONFIG'} ||= $test_config;
+    $ENV{'JIFTY_TEST_CONFIG'} ||= "$test_config";
     $class->builder->{test_config} = $test_config;
     {
         # Cache::Memcached stores things. And doesn't let them expire
@@ -187,7 +187,7 @@
     # Mason's disk caching sometimes causes false tests
     rmtree([ File::Spec->canonpath("$root/var/mason") ], 0, 1);
 
-$class->setup_test_database;
+    $class->setup_test_database;
 
     $class->setup_mailbox;
 }

Modified: jifty/branches/autoversioning/lib/Jifty/Test/WWW/Mechanize.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Test/WWW/Mechanize.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Test/WWW/Mechanize.pm	Sun Jul 22 21:13:55 2007
@@ -436,7 +436,10 @@
 sub session {
     my $self = shift;
 
-    return undef unless $self->cookie_jar->as_string =~ /JIFTY_SID_\d+=([^;]+)/;
+    my $cookie = Jifty->config->framework('Web')->{'SessionCookieName'};
+    $cookie =~ s/\$PORT/(?:\\d+|NOPORT)/g;
+
+    return undef unless $self->cookie_jar->as_string =~ /$cookie=([^;]+)/;
 
     my $session = Jifty::Web::Session->new;
     $session->load($1);

Modified: jifty/branches/autoversioning/lib/Jifty/Upgrade.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Upgrade.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Upgrade.pm	Sun Jul 22 21:13:55 2007
@@ -3,7 +3,7 @@
 
 =head1 NAME
 
-Jifty::Upgrade
+Jifty::Upgrade - Superclass for schema/data upgrades to Jifty applicaitons
 
 =head1 DESCRIPTION
 
@@ -152,4 +152,12 @@
     $package->just_renamed($renamed);
 }
 
+
+
+=head1 SEE ALSO
+
+L<Jifty::Manual::Upgrading>
+
+=cut
+
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Upgrade/Internal.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Upgrade/Internal.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Upgrade/Internal.pm	Sun Jul 22 21:13:55 2007
@@ -9,6 +9,12 @@
 # XXX TODO: there's probably a cleaner way to cope than "INITIAL_VERSION", perhaps using ->VERSIONS
 our $INITIAL_VERSION;
 
+=head1 NAME
+
+Jifty::Upgrade::Internal - Upgrades to Jifty-specific schemas and data
+
+=head1 UPGRADES
+
 =head2 Version 0.60427
 
 Version metadata, previously stored in _db_version, get migrated to

Modified: jifty/branches/autoversioning/lib/Jifty/Util.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Util.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Util.pm	Sun Jul 22 21:13:55 2007
@@ -94,7 +94,8 @@
 =head2 share_root
 
 Returns the 'share' directory of the installed Jifty module.  This is
-currently only used to store the common Mason components.
+currently only used to store the common Mason components, CSS, and JS
+of Jifty and it's plugins.
 
 =cut
 
@@ -245,7 +246,7 @@
             return 0;
         }
         elsif ( $UNIVERSAL::require::ERROR !~ /^Can't locate/) {
-                die $UNIVERSAL::require::ERROR;
+            die $UNIVERSAL::require::ERROR;
         } else {
             Jifty->log->error(sprintf("$error at %s line %d\n", (caller(1))[1,2]));
             return 0;

Added: jifty/branches/autoversioning/lib/Jifty/View.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/View.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,68 @@
+package Jifty::View;
+use strict;
+use warnings;
+
+=head1 NAME
+
+Jifty::View - Base class for view modules
+
+=head1 DESCRIPTION
+
+This is the base class for L<Jifty::View::Declare> and L<Jifty::View::Mason::Handler>, which are the two view plugins shipped with Jifty. Other view plugins can be built by extending this class.
+
+=head1 METHODS
+
+=head2 auto_send_headers
+
+Doesn't send headers if this is a subrequest (according to the current
+L<Jifty::Request>).
+
+=cut
+
+sub auto_send_headers {
+    return not Jifty->web->request->is_subrequest;
+}
+
+=head2 out_method
+
+The default output method.  Sets the content-type to C<text/html;
+charset=utf-8> unless a content type has already been set, and then
+sends a header if need be.
+
+=cut
+
+sub out_method {
+    my $r = Jifty->handler->apache;
+
+    $r->content_type || $r->content_type('text/html; charset=utf-8'); # Set up a default
+
+    unless ( $r->http_header_sent or not __PACKAGE__->auto_send_headers ) {
+        $r->send_http_header();
+    }
+
+    # We could perhaps install a new, faster out_method here that
+    # wouldn't have to keep checking whether headers have been
+    # sent and what the $r->method is.  That would require
+    # additions to the Request interface, though.
+    binmode *STDOUT;
+    if ( my ($enc) = $r->content_type =~ /charset=([\w-]+)$/ ) {
+        print STDOUT map Encode::encode($enc, $_), grep {defined} @_;
+    } else {
+        print STDOUT grep {defined} @_;
+    }
+}
+
+=head1 SEE ALSO
+
+L<Jifty::View::Declare>, L<Jifty::View::Declare::BaseClass>, L<Jifty::View::Mason::Handler>
+
+=head1 LICENSE
+
+Jifty is Copyright 2005-2007 Best Practical Solutions, LLC.
+Jifty is distributed under the same terms as Perl itself.
+
+=cut
+
+
+
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/View/Declare.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Declare.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare.pm	Sun Jul 22 21:13:55 2007
@@ -5,6 +5,10 @@
 use warnings;
 use constant BaseClass => 'Jifty::View::Declare::BaseClass';
 
+=head1 NAME
+
+Jifty::View::Declare - Build views using Template::Declare
+
 =head1 SYNOPSIS
 
     package MyApp::View;
@@ -15,6 +19,19 @@
         b { "The Index" };
     };
 
+=head1 DESCRIPTION
+
+L<Template::Declare> is a templating system using a declarative syntax built on top of Perl. This provides a templating language built in a similar style to the dispatcher language in L<Jifty::Dispatcher>, the model language in L<Jifty::DBI::Schema>, and the action language in L<Jifty::Param::Schema>.
+
+To use this view system, you must declare a class named C<MyApp::View> (where I<MyApp> is the name of your Jifyt application). Use this library class to bring in all the details needed to make it work:
+
+  package MyApp::View;
+  use Jifty::View::Declare -base;
+
+  # Your code...
+
+For more details on how to write the individual templates, see L<Template::Declare> and also L<Jifty::View::Declare::Helpers> for Jifty specific details.
+
 =cut
 
 sub import {
@@ -29,4 +46,15 @@
     goto &{BaseClass()->can('import')};
 }
 
+=head1 SEE ALSO 
+
+L<Jifty::View::Declare::Helpers>, L<Template::Declare>
+
+=head1 LICENSE
+
+Jifty is Copyright 2005-2007 Best Practical Solutions, LLC.
+Jifty is distrib uted under the same terms as Perl itself.
+
+=cut
+
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/View/Declare/BaseClass.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Declare/BaseClass.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare/BaseClass.pm	Sun Jul 22 21:13:55 2007
@@ -12,25 +12,62 @@
 
 our @EXPORT = ( @Jifty::View::Declare::Helpers::EXPORT);
 
-
-1;
-__DATA__
-
 =head1 NAME
 
-Jifty::View::Declare::BaseClass
+Jifty::View::Declare::BaseClass - Base class for Template::Declare views
 
 =head1 DESCRIPTION
 
-This class provides a baseclass for your C<Template::Declare> derived view classes.
-
+This class provides a base class for your L<Template::Declare> derived view classes.
 
 =head1 METHODS
 
+=head2 use_mason_wrapper
+
+Call this function in your view class to use your mason wrapper for L<Template::Declare> templates.
+
+=cut
+
+sub use_mason_wrapper {
+    my $class = shift;
+    no strict 'refs';
+    no warnings 'redefine';
+    *{ $class . '::wrapper' } = sub {
+        my $code = shift;
+        my $args = shift;
+        # so in td handler, we made jifty::web->out appends to td
+        # buffer, we need it back for here before we call $code.
+        # someday we need to finish fixing the output system that is
+        # in Jifty::View.
+        my $td_out = \&Jifty::Web::out;
+        local *Jifty::Web::out = sub { shift->mason->out(@_) };
+
+        local *HTML::Mason::Request::content = sub {
+            local *Jifty::Web::out = $td_out;
+            $code->();
+            my $content = Template::Declare->buffer->data;
+            Template::Declare->buffer->clear;
+            $content;
+        };
+
+        Jifty->handler->fallback_view_handler->show('/_elements/wrapper', $args);
+    }
+}
+
+
 =head2 show templatename arguments
 
 Render a C<Template::Declare> template.
 
+=head1 SEE ALSO
+
+L<Template::Declare>, L<Jifty::View::Declare::Helpers>, L<Jifty::View::Declare>
+
+=head1 LICENSE
+
+Jifty is Copyright 2005-2007 Best Practical Solutions, LLC.
+Jifty is distributed under the same terms as Perl itself.
 
 =cut
 
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/View/Declare/CRUD.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Declare/CRUD.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare/CRUD.pm	Sun Jul 22 21:13:55 2007
@@ -3,14 +3,56 @@
 
 package Jifty::View::Declare::CRUD;
 use Jifty::View::Declare -base;
-use base 'Exporter';
-our @EXPORT = qw(object_type fragment_for get_record current_collection);
+
+
+=head1 NAME
+
+Jifty::View::Declare::CRUD - Provides typical CRUD views to a model
+
+=head1 DESCRIPTION
+
+This class provides a set of views that may be used by a model to
+display Create/Read/Update/Delete views using the L<Template::Declare>
+templating language.
+
+=head1 METHODS
+
+=cut
+
+
+=head2 mount_view MODELCASS VIEWCLASS /path
+
+=cut
+
+sub mount_view {
+    my ($class, $model, $vclass, $path) = @_;
+    my $caller = caller(0);
+    $model = ucfirst($model);
+    $vclass ||= $caller.'::'.$model;
+    $path ||= '/'.lc($model);
+
+    Jifty::Util->require($vclass);
+    eval qq{package $caller;
+            alias $vclass under '$path'; 1} or die $@;
+    no strict 'refs';
+    *{$vclass."::object_type"} = sub { $model };
+}
+
+
+=head2 object_type
+
+=cut
 
 sub object_type {
     my $self = shift;
     return $self->package_variable('object_type') || get('object_type');
 }
 
+
+=head2 fragment_for
+
+=cut
+
 sub fragment_for {
     my $self     = shift;
     my $fragment = shift;
@@ -23,12 +65,25 @@
         || $self->fragment_base_path . "/" . $fragment;
 }
 
+=head2 fragment_base_path
+
+=cut
+
 sub fragment_base_path {
     my $self = shift;
-    return $self->package_variable('base_path') || '/crud';
+    my @parts = split('/', current_template());
+    pop @parts;
+    my $path = join('/', @parts);
+    return $path;
 }
 
-sub get_record {
+=head2 _get_record $id
+
+Given an $id, returns a record object for the CRUD view's model class.
+
+=cut
+
+sub _get_record {
     my ( $self, $id ) = @_;
 
     my $record_class = Jifty->app_class( "Model", $self->object_type );
@@ -38,6 +93,51 @@
     return $record;
 }
 
+=head2 display_columns
+
+Returns a list of all the columns that this REST view should display
+
+=cut
+
+sub display_columns {
+    my $self = shift;
+    my $action = shift;
+     return   grep { !( m/_confirm/ || lc $action->arguments->{$_}{render_as} eq 'password' ) } $action->argument_names;
+}
+
+
+=head1 TEMPLATES
+
+
+=cut
+
+=head2 index.html
+
+
+=cut
+
+
+template 'index.html' => page {
+    my $self = shift;
+    title is $self->object_type;
+    form {
+            render_region(
+                name     => $self->object_type.'-list',
+                path     => $self->fragment_base_path.'/list');
+    }
+
+};
+
+ 
+
+
+
+=head2 search
+
+The search view displays a search screen connected to the search action of the module. See L<Jifty::Action::Record::Search>.
+
+=cut
+
 template 'search' => sub {
     my $self          = shift;
     my ($object_type) = ( $self->object_type );
@@ -63,35 +163,58 @@
         }
 };
 
+
+=head2 view
+
+This template displays the data held by a single model record.
+
+=cut
+
 template 'view' => sub {
     my $self = shift;
     my ( $object_type, $id ) = ( $self->object_type, get('id') );
+      my $record =   $self->_get_record($id);
     my $update = new_action(
         class   => 'Update' . $object_type,
         moniker => "update-" . Jifty->web->serial,
-        record  => $self->get_record($id)
+        record  => $record 
     );
 
     div {
         { class is 'crud read item inline' };
+        my @fields =$self->display_columns($update);
+        render_action( $update, \@fields, { render_mode => 'read' } );
+
+        show ('./view_item_controls', $record, $update); 
+
+        hr {};
+    };
+
+};
+
+private template view_item_controls  => sub {
+    my $self = shift;
+    my $record = shift;
+
+    if ( $record->current_user_can('update') ) {
         hyperlink(
-            label   => "Edit",
+            label   => _("Edit"),
             class   => "editlink",
             onclick => {
                 replace_with => $self->fragment_for('update'),
-                args         => { object_type => $object_type, id => $id }
+                args         => { object_type => $self->object_type, id => $record->id }
             },
         );
+    }
+};
 
-        my @fields = grep {
-            !( m/_confirm/
-                || lc $update->arguments->{$_}{render_as} eq 'password' )
-        } $update->argument_names;
-        render_action( $update, \@fields, { render_mode => 'read' } );
-        hr {};
-    };
 
-};
+
+=head2 update
+
+The update template displays a form for editing the data held within a single model record. See L<Jifty::Action::Record::Update>.
+
+=cut
 
 template 'update' => sub {
     my $self = shift;
@@ -109,6 +232,35 @@
     div {
         { class is "crud update item inline " . $object_type }
 
+        show('./edit_item', $update);
+        show('./edit_item_controls', $record, $update);
+
+        hr {};
+        }
+};
+
+
+
+=head2 edit_item_controls $record $action
+
+The controls we should be rendering in the 'edit' region for a given fragment
+
+=cut
+
+private template edit_item_controls => sub {
+    my $self = shift;
+    my $record = shift;
+    my $update = shift;
+
+    my $object_type = $self->object_type;
+    my $id = $record->id;
+
+    my $delete = Jifty->web->form->add_action(
+        class   => 'Delete' . $object_type,
+        moniker => 'delete-' . Jifty->web->serial,
+        record  => $record
+    );
+
         div {
             { class is 'crud editlink' };
             hyperlink(
@@ -126,50 +278,71 @@
                     replace_with => $self->fragment_for('view'),
                     args         => { object_type => $object_type, id => $id }
                 },
-                as_button => 1
+                as_button => 1,
+                class => 'cancel'
             );
+            if ( $record->current_user_can('delete') ) {
+                $delete->button(
+                    label   => 'Delete',
+                    onclick => {
+                        submit => $delete,
+                        confirm => 'Really delete?',
+                        refresh => Jifty->web->current_region->parent,
+                    },
+                    class => 'delete'
+                );
+            }
         };
 
-        render_action($update);
-        hr {};
-        }
 };
 
+=head2 list
+
+The list template provides an interactive list for showing a list of records in the record collection, adding new records, deleting records, and updating records.
+
+=cut
+
+template 'list' => sub {
+    my $self = shift;
+
+    my ( $page ) = get(qw(page ));
+    my $item_path = get('item_path') || $self->fragment_for("view");
+    my $collection =  $self->_current_collection();
 
-sub current_collection {
+    show('./search_region');
+    show( './paging_top',    $collection, $page );
+    show( './list_items',    $collection, $item_path );
+    show( './paging_bottom', $collection, $page );
+    show( './new_item_region');
+
+};
+
+sub per_page { 25 }
+
+sub _current_collection {
     my $self =shift; 
     my ( $page, $search_collection ) = get(qw(page  search_collection));
-
     my $collection_class = Jifty->app_class( "Model", $self->object_type . "Collection" );
-    my $search = $search_collection || Jifty->web->response->result('search');
+    my $search = $search_collection || ( Jifty->web->response->result('search') ? Jifty->web->response->result('search')->content('search') : undef );
     my $collection;
-    if ( !$search ) {
+    if ( $search ) {
+        $collection = $search;
+    } else {
         $collection = $collection_class->new();
         $collection->unlimit();
-    } else {
-        $collection = $search->content('search');
     }
 
-    $collection->set_page_info( current_page => $page, per_page => 25 );
+    $collection->set_page_info( current_page => $page, per_page => $self->per_page );
 
     return $collection;    
 }
 
-template 'list' => sub {
-    my $self = shift;
 
-    my ( $page, $search_collection ) = get(qw(page  search_collection));
-    my $fragment_for_new_item = get('fragment_for_new_item') || $self->fragment_for('new_item');
-    my $item_path = get('item_path') || $self->fragment_for("view");
+=head2 search_region
 
-    my $collection =  $self->current_collection();
-    show('./search_region');
-    show( './paging_top',    $collection, $page );
-    show( './list_items',    $collection, $item_path );
-    show( './paging_bottom', $collection, $page );
-    show( './new_item_region', $fragment_for_new_item );
+This I<private> template renders a region to show an expandable region for a search widget.
 
-};
+=cut
 
 private template 'search_region' => sub {
     my $self        = shift;
@@ -193,9 +366,17 @@
 
     outs( $search_region->render );
 };
+
+=head2 new_item_region
+
+This I<private> template renders a region to show a the C<new_item> template.
+
+=cut
+
+
 private template 'new_item_region' => sub {
     my $self        = shift;
-    my $fragment_for_new_item = shift;
+    my $fragment_for_new_item = get('fragment_for_new_item') || $self->fragment_for('new_item');
     my $object_type = $self->object_type;
 
     if ($fragment_for_new_item) {
@@ -207,13 +388,24 @@
     }
 };
 
+
+=head2 list_items $collection $item_path
+
+Renders a div of class list with a region per item.
+
+
+
+=cut
+
+private template 'no_items_found' => sub { outs(_("No items found.")) };
+
 private template 'list_items' => sub {
     my $self        = shift;
     my $collection  = shift;
     my $item_path   = shift;
     my $object_type = $self->object_type;
     if ( $collection->pager->total_entries == 0 ) {
-        outs( _("No items found") );
+        show('no_items_found');
     }
 
     div {
@@ -229,6 +421,14 @@
 
 };
 
+
+=head2 paging_top $collection $page_number
+
+Paging for your list, rendered at the top of the list
+
+=cut
+
+
 private template 'paging_top' => sub {
     my $self       = shift;
     my $collection = shift;
@@ -244,6 +444,12 @@
 
 };
 
+=head2 paging_bottom $collection $page_number
+
+Paging for your list, rendered at the bottom of the list
+
+=cut
+
 private template paging_bottom => sub {
     my $self       = shift;
     my $collection = shift;
@@ -254,7 +460,7 @@
             span {
                 { class is 'prev-page' };
                 hyperlink(
-                    label   => "Previous Page",
+                    label   => _("Previous Page"),
                     onclick => {
                         args => { page => $collection->pager->previous_page }
                     }
@@ -265,7 +471,7 @@
             span {
                 { class is 'next-page' };
                 hyperlink(
-                    label   => "Next Page",
+                    label   => _("Next Page"),
                     onclick =>
                         { args => { page => $collection->pager->next_page } }
                 );
@@ -274,6 +480,28 @@
     };
 };
 
+
+
+=head2 edit_item $action
+
+Renders the action $Action, handing it the array ref returned by L</display_columns>.
+
+=cut
+
+
+
+private template 'edit_item' => sub {
+    my $self = shift;
+    my $action = shift;
+    render_action($action, [$self->display_columns($action)]);
+};
+
+=head1 new_item
+
+The new_item template provides a form for creating new model records. See L<Jifty::Action::Record::Create>.
+
+=cut
+
 template 'new_item' => sub {
     my $self = shift;
     my ( $object_type, $id ) = ( $self->object_type, get('id') );
@@ -283,7 +511,7 @@
 
     div {
         { class is 'crud create item inline' };
-        render_action($create);
+        show('./edit_item', $create);
 
         outs(
             Jifty->web->form->submit(
@@ -306,5 +534,16 @@
         }
 };
 
+=head1 SEE ALSO
+
+L<Jifty::Action::Record::Create>, L<Jifty::Action::Record::Search>, L<Jifty::Action::Record::Update>, L<Jifty::Action::Record::Delete>, L<Template::Declare>, L<Jifty::View::Declare::Helpers>, L<Jifty::View::Declare>
+
+=head1 LICENSE
+
+Jifty is Copyright 2005-2007 Best Practical Solutions, LLC.
+Jifty is distributed under the same terms as Perl itself.
+
+=cut
+
 1;
 

Modified: jifty/branches/autoversioning/lib/Jifty/View/Declare/CoreTemplates.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Declare/CoreTemplates.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare/CoreTemplates.pm	Sun Jul 22 21:13:55 2007
@@ -9,7 +9,7 @@
 
 =head1 NAME 
 
-Jifty::View::Declare::CoreTemplates
+Jifty::View::Declare::CoreTemplates - Templates Jifty can't function without
 
 =head1 DESCRIPTION
 

Modified: jifty/branches/autoversioning/lib/Jifty/View/Declare/Handler.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Declare/Handler.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare/Handler.pm	Sun Jul 22 21:13:55 2007
@@ -10,7 +10,7 @@
 
 =head1 NAME
 
-Jifty::View::Declare::Handler
+Jifty::View::Declare::Handler - The Jifty view handler for Template::Declare
 
 =head1 METHODS
 
@@ -74,7 +74,8 @@
         shift;    # Turn the method into a function
         goto &Template::Declare::Tags::outs_raw;
     };
-    my $content = Template::Declare::Tags::show_page( $template );
+    
+    my $content = Template::Declare::Tags::show_page( $template, Jifty->web->request->arguments );
     return unless defined $content && length $content;
 
     my $r = Jifty->handler->apache;

Modified: jifty/branches/autoversioning/lib/Jifty/View/Declare/Helpers.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Declare/Helpers.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare/Helpers.pm	Sun Jul 22 21:13:55 2007
@@ -2,16 +2,14 @@
 use strict;
 
 package Jifty::View::Declare::Helpers;
-use base qw/Template::Declare/;
-use base qw/Exporter/;
+use base qw/Template::Declare Exporter/;
 use Template::Declare::Tags;
 
-our @EXPORT = ( qw(form hyperlink tangent redirect new_action form_submit form_return  form_next_page page wrapper request get set render_param current_user render_action render_region), @Template::Declare::Tags::EXPORT);
-
+our @EXPORT = ( qw(form hyperlink tangent redirect new_action form_submit form_return form_next_page page content wrapper request get set render_param current_user render_action render_region), @Template::Declare::Tags::EXPORT);
 
 =head1 NAME
 
-Jifty::View::Declare::Helpers
+Jifty::View::Declare::Helpers - Additional subroutines for Jifty TD templates
 
 =head1 DESCRIPTION
 
@@ -266,27 +264,44 @@
 
  template 'foo' => page {{ title is 'Foo' } ... };
 
+  or
+
+ template 'foo' => page { title => 'Foo' } content { ... };
+
 Renders an HTML page wrapped in L</wrapper>, after calling
 "/_elements/nav" and setting a content type. Generally, you shouldn't
 be using "/_elements/nav" but a Dispatcher rule instead.
 
+If C<page/content> calling convention is used, the return value of the
+first sub will be passed into wrapper as the second argument as a
+hashref, as well as the last argument for the content sub.
+
 =cut
 
-sub page (&) {
-    my $code = shift;
+sub page (&;$) {
+    unshift @_, undef if $#_ == 0;
+    my ( $meta, $code ) = @_;
     sub {
         my $self = shift;
         Jifty->handler->apache->content_type('text/html; charset=utf-8');
-        if ( my $wrapper = Jifty->app_class('View')->can('wrapper') ) {
-            $wrapper->(sub { $code->($self)});
-        } else {
-
-        wrapper(sub { $code->($self) });
+        my $wrapper = Jifty->app_class('View')->can('wrapper') || \&wrapper;
+        my @metadata = $meta ? $meta->() : ();
+        my $metadata = $#metadata == 0 ? $metadata[0] : {@metadata};
+        local *is::title = sub { warn "Can't use 'title is' when mixing mason and TD" };
+        $wrapper->( sub { $code->( $self, $metadata ) }, $metadata );
     }
-    };
 }
 
+=head2 content
 
+Helper function for page { ... } content { ... }
+
+=cut
+
+sub content (&;$) {
+    # XXX: Check for only 1 arg
+    return $_[0];
+}
 
 =head2 wrapper $coderef
 
@@ -295,112 +310,42 @@
 
 =cut
 
-sub wrapper ($) {
-    my $content_code = shift;
-    my ($title) = get_current_attr(qw(title));
-
-    my $done_header;
-    my $render_header = sub {
-        no warnings qw( uninitialized redefine once );
-        $title ||= Jifty->config->framework('ApplicationName');
-
-        #   defined $title or return;
-        return if $done_header++;
-        Template::Declare->new_buffer_frame;
-        outs_raw(
-        '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
-            . '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' );
-        render_header($title);
-        $done_header = Template::Declare->buffer->data;
-        Template::Declare->end_buffer_frame;
-        return '';
-    };
-
-    body {
-        div {
-            div {
-            show 'salutation'; 
-            show 'menu'; 
-        };
-            div { attr { id is 'content'};
-                div {
-                    {
-                        no warnings qw( uninitialized redefine once );
-
-                        local *is::title = sub {
-                            shift;
-                            for (@_) {
-                                if ( ref($_) eq 'CODE' ) {
-                                    Template::Declare->new_buffer_frame;
-                                    $_->();
-                                    $title .= Template::Declare->buffer->data;
-                                    Template::Declare->end_buffer_frame;
-                                } else {
-                                    $title .= Jifty->web->escape($_);
-                                }
-                            }
-                            &$render_header;
-                            my $oldt = get('title'); set(title => $title);
-                            show 'heading_in_wrapper';
-                            set(title => $oldt);
-                        };
-
-                        &_render_pre_content_hook();
-                        Jifty->web->render_messages;
-                        &$content_code;
-                        &$render_header unless ($done_header);
-                        &_render_jifty_page_detritus();
-                }
-
-                };
-            };
-        };
-    };
-    outs_raw('</html>');
-    Template::Declare->buffer->data( $done_header . Template::Declare->buffer->data );
-}
-
-sub _render_pre_content_hook {
-    if ( Jifty->config->framework('AdminMode') ) {
-        with( class => "warning admin_mode" ), div {
-            outs( _('Alert') . ': ' );
-            outs_raw(
-                Jifty->web->tangent(
-                    label => _('Administration mode is enabled.'),
-                    url   => '/__jifty/admin/'
-                )
-            );
-            }
+sub wrapper {
+    my $app_class = get_current_attr('PageClass') || 'View::Page';
+    delete $Template::Declare::Tags::ATTRIBUTES{ 'PageClass' };
+
+    my $page_class = Jifty->app_class( $app_class );
+    $page_class = 'Jifty::View::Declare::Page'
+        unless Jifty::Util->_require( module => $page_class, quiet => 1 );
+    # XXX: fallback, this is ugly
+    Jifty::Util->require( $page_class );
+
+    my $page = $page_class->new({ content_code => shift });
+
+    my ($spa) = Jifty->find_plugin('Jifty::Plugin::SinglePage');
+
+    # XXX: spa hooks should be moved to page handlers
+    if ($spa && $page->allow_single_page) {
+	# If it's a single page app, we want to either render a
+	# wrapper and then get the region or render just the content
+        if ( !Jifty->web->current_region ) {
+	    $page->render_header;
+            $page->render_body(sub {
+                render_region( $spa->region_name,
+                    path => Jifty->web->request->path );
+            });
+	    $page->render_footer;
+        } else {
+	    $page->done_header(1);
+	    $page->render_page->();
+        }
     }
-}
-
-sub _render_jifty_page_detritus {
-
-    show('keybindings');
-    with( id => "jifty-wait-message", style => "display: none" ),
-        div { _('Loading...') };
-
-    # This is required for jifty server push.  If you maintain your own
-    # wrapper, make sure you have this as well.
-    if ( Jifty->config->framework('PubSub')->{'Enable'} && Jifty::Subs->list )
-    {
-        script { outs('new Jifty.Subs({}).start();') };
+    else {
+	$page->render_body( sub { $page->render_page->() });
+	$page->render_footer;
     }
 }
 
-=head2 render_header $title
-
-Renders an HTML "doctype", <head> and the first part of a page body. This bit isn't terribly well thought out and we're not happy with it.
-
-=cut
-
-sub render_header { 
-    my $title = shift || '';
-    $title =~ s/<.*?>//g;    # remove html
-    HTML::Entities::decode_entities($title);
-    with( title => $title ), show('header');
-}               
-                    
 
 
 

Added: jifty/branches/autoversioning/lib/Jifty/View/Declare/Page.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/lib/Jifty/View/Declare/Page.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,210 @@
+package Jifty::View::Declare::Page;
+use strict;
+use warnings;
+use base qw/Template::Declare Class::Accessor::Fast/;
+use Template::Declare::Tags;
+
+=head1 NAME
+
+Jifty::View::Declare::Page
+
+=head1 DESCRIPTION
+
+This library provides page wrappers
+
+=head1 METHODS
+
+=cut
+
+use Jifty::View::Declare::Helpers;
+
+__PACKAGE__->mk_accessors(qw(content_code done_header _title));
+use constant allow_single_page => 1;
+
+=head2 new
+
+Sets up a new page class
+
+=cut
+
+sub new {
+    my $class = shift;
+    my $self = $class->SUPER::new(@_);
+
+    my ($title) = get_current_attr(qw(title));
+    $self->_title($title);
+
+    return $self;
+}
+
+=head2 render_header $title
+
+Renders an HTML "doctype", <head> and the first part of a page body. This bit isn't terribly well thought out and we're not happy with it.
+
+=cut
+
+sub render_header {
+    my $self = shift;
+    return if $self->done_header;
+
+    Template::Declare->new_buffer_frame;
+    outs_raw(
+        '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' . "\n"
+      . '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">' . "\n" );
+
+    $self->_render_header($self->_title || Jifty->config->framework('ApplicationName'));
+
+    $self->done_header(Template::Declare->buffer->data);
+    Template::Declare->end_buffer_frame;
+    return '';
+};
+
+=head2 render_body $body_code
+
+Renders $body_code inside a body tag
+
+=cut
+
+sub render_body {
+    my ($self, $body_code) = @_;
+
+    body { $body_code->() };
+}
+
+=head2 render_page
+
+Renders the skeleton of the page
+
+=cut
+
+sub render_page {
+    my $self = shift;
+
+    div {
+        div {
+            show '/salutation';
+            show '/menu';
+        };
+        div {
+            attr { id is 'content' };
+            div {
+                {
+                    no warnings qw( redefine once );
+
+                    local *is::title = $self->mk_title_handler();
+                    $self->render_pre_content_hook();
+                    Jifty->web->render_messages;
+
+                    $self->content_code->();
+                    $self->render_header();
+
+                    $self->render_jifty_page_detritus();
+                }
+
+            };
+        };
+    };
+}
+
+=head2 mk_title_handler
+
+Returns a coderef that will make headers for each thing passed to it
+
+=cut
+
+sub mk_title_handler {
+    my $self = shift;
+    return sub {
+        shift;
+        for (@_) {
+	    no warnings qw( uninitialized );
+            if ( ref($_) eq 'CODE' ) {
+                Template::Declare->new_buffer_frame;
+                $_->();
+                $self->_title(
+                    $self->_title . Template::Declare->buffer->data );
+                Template::Declare->end_buffer_frame;
+            } else {
+                $self->_title( $self->_title . Jifty->web->escape($_) );
+            }
+        }
+        $self->render_header;
+	$self->render_title();
+    };
+}
+
+=head2 render_title
+
+Renders the in-page title
+
+=cut
+
+sub render_title {
+    my $self = shift;
+    my $oldt = get('title');
+    set( title => $self->_title );
+    show '/heading_in_wrapper';
+    set( title => $oldt );
+}
+
+=head2 render_footer
+
+Renders the page footer and prepends the header to the L<Template::Declare> buffer.
+
+=cut
+
+sub render_footer {
+    my $self = shift;
+    outs_raw('</html>');
+    Template::Declare->buffer->data( $self->done_header . Template::Declare->buffer->data );
+}
+
+=head2 render_pre_content_hook
+
+Renders the AdminMode alert (if AdminMode is on)
+
+=cut
+
+sub render_pre_content_hook {
+    if ( Jifty->config->framework('AdminMode') ) {
+        with( class => "warning admin_mode" ), div {
+            outs( _('Alert') . ': ' );
+            outs_raw(
+                Jifty->web->tangent(
+                    label => _('Administration mode is enabled.'),
+                    url   => '/__jifty/admin/'
+                )
+            );
+            }
+    }
+}
+
+=head2 render_jifty_page_detritus
+
+Renders the keybinding and PubSub javascript as well as the wait message
+
+=cut
+
+sub render_jifty_page_detritus {
+
+    show('/keybindings');
+    with( id => "jifty-wait-message", style => "display: none" ),
+        div { _('Loading...') };
+
+    # This is required for jifty server push.  If you maintain your own
+    # wrapper, make sure you have this as well.
+    if ( Jifty->config->framework('PubSub')->{'Enable'} && Jifty::Subs->list )
+    {
+        script { outs('new Jifty.Subs({}).start();') };
+    }
+}
+
+sub _render_header { 
+    my $self = shift;
+    my $title = shift || '';
+    $title =~ s/<.*?>//g;    # remove html
+    HTML::Entities::decode_entities($title);
+    with( title => $title ), show('/header');
+}
+
+1;

Modified: jifty/branches/autoversioning/lib/Jifty/View/Mason/Handler.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Mason/Handler.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Mason/Handler.pm	Sun Jul 22 21:13:55 2007
@@ -23,7 +23,7 @@
 use Encode qw();
 
 use Class::Container;
-use base qw(Class::Container);
+use base qw(Jifty::View Class::Container);
 
 use HTML::Mason::MethodMaker
     ( read_write => [ qw( interp ) ] );
@@ -56,7 +56,7 @@
 
     my %p = @_ || $package->config;
     my $self = $package->SUPER::new( request_class => 'HTML::Mason::Request::Jifty',
-                                     out_method => \&out_method,
+                                     out_method => $package->can('out_method'),
                                      %p );
     $self->interp->compiler->add_allowed_globals('$r');
     $self->interp->set_escape( h => \&escape_utf8 );
@@ -117,37 +117,6 @@
     return %config;
 }
 
-=head2 out_method
-
-The default output method.  Sets the content-type to C<text/html;
-charset=utf-8> unless a content type has already been set, and then
-sends a header if need be.
-
-=cut
-
-sub out_method {
-    my $m = HTML::Mason::Request->instance;
-    my $r = Jifty->handler->apache;
-
-    $r->content_type || $r->content_type('text/html; charset=utf-8'); # Set up a default
-
-    unless ( $r->http_header_sent or not $m->auto_send_headers ) {
-        $r->send_http_header();
-    }
-
-    # We could perhaps install a new, faster out_method here that
-    # wouldn't have to keep checking whether headers have been
-    # sent and what the $r->method is.  That would require
-    # additions to the Request interface, though.
-    binmode *STDOUT;
-    if ( my ($enc) = $r->content_type =~ /charset=([\w-]+)$/ ) {
-        print STDOUT map Encode::encode($enc, $_), grep {defined} @_;
-    } else {
-        print STDOUT grep {defined} @_;
-    }
-}
-
-
 =head2 escape_utf8 SCALARREF
 
 Does a css-busting but minimalist escaping of whatever html you're passing in.
@@ -214,13 +183,13 @@
 }
 
 sub handle_comp {
-    my ($self, $comp) = (shift, shift);
+    my ($self, $comp, $args) = @_;
 
     # Set up the global
     my $r = Jifty->handler->apache;
     $self->interp->set_global('$r', $r);
 
-    my %args = $self->request_args($r);
+    my %args = $args ? %$args : $self->request_args($r);
 
     my @result;
     if (wantarray) {
@@ -280,7 +249,7 @@
 =cut
 
 sub auto_send_headers {
-    return not Jifty->web->request->is_subrequest;
+    Jifty::View->auto_send_headers;
 }
 
 =head2 exec

Modified: jifty/branches/autoversioning/lib/Jifty/View/Static/Handler.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/View/Static/Handler.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/View/Static/Handler.pm	Sun Jul 22 21:13:55 2007
@@ -14,7 +14,7 @@
 
 =head1 NAME
 
-Jifty::View::Static::Handler
+Jifty::View::Static::Handler - Jifty view handler for static files
 
 head1 DESCRIPTION
 
@@ -24,7 +24,7 @@
 
 * Static files are served out of a separate root
 * If static files go through apache:
-    * How do we merge together the two static roots?
+    * How do we merge together the N static roots?
 * If static files go through Jifty::Handler
     * We need a flag to allow them to go through the dispatcher, too
     * return "True" (304) for if-modified-since
@@ -50,10 +50,30 @@
 =cut
 sub new {
     my $class = shift;
-    my $self = {};
-    bless $self, $class;
+    
+    my @roots = (Jifty->config->framework('Web')->{StaticRoot});
+    for my $plugin ( Jifty->plugins ) {
+        my $root = $plugin->static_root;
+        if ( -d $root and -r $root ) {
+            push @roots, $root;
+            Jifty->log->debug( "Plugin @{[ref($plugin)]} static root added: (@{[$root ||'']})");
+        }
+    }
+    push @roots, (Jifty->config->framework('Web')->{DefaultStaticRoot});
+
+    return bless { roots => \@roots }, $class;
 }
 
+=head2 roots
+
+Returns all the static roots the handler will search
+
+=cut
+
+sub roots {
+    my $self = shift;
+    return wantarray ? @{$self->{roots}} : $self->{roots};
+}
 
 =head2 show $path
 
@@ -138,14 +158,11 @@
 sub file_path {
     my $self    = shift;
     my $file    = shift;
-    my @options = (Jifty->config->framework('Web')->{StaticRoot});
-    push @options, grep { -d $_ && -r $_ } map {$_->static_root} Jifty->plugins;
-    push @options, (Jifty->config->framework('Web')->{DefaultStaticRoot});
 
     # Chomp a leading "/static" - should this be configurable?
     $file =~ s/^\/*?static//; 
 
-    foreach my $path (@options) {
+    foreach my $path ( $self->roots ) {
         my $abspath = Jifty::Util->absolute_path( File::Spec->catdir($path,$file ));
         # If the user is trying to request something outside our static root, 
         # decline the request

Modified: jifty/branches/autoversioning/lib/Jifty/Web.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web.pm	Sun Jul 22 21:13:55 2007
@@ -26,8 +26,12 @@
 );
 
 __PACKAGE__->mk_classdata($_)
-    for qw(cached_css        cached_css_digest        cached_css_time
-           cached_javascript cached_javascript_digest cached_javascript_time javascript_libs);
+    for qw(cached_css cached_css_digest cached_css_time
+           css_files  javascript_libs   external_javascript_libs);
+
+__PACKAGE__->css_files([qw( main.css )]);
+
+__PACKAGE__->external_javascript_libs([]);
 
 __PACKAGE__->javascript_libs([qw(
     jsan/JSAN.js
@@ -71,6 +75,8 @@
     css_browser_selector.js
 )]);
 
+use Jifty::DBI::Class::Trigger;
+
 =head1 METHODS
 
 =head3 new
@@ -106,8 +112,8 @@
 =cut
 
 sub out {
-    Carp::cluck unless defined $_[0]->mason;
-    shift->mason->out(@_);
+    my $m = shift->mason;
+    $m ? $m->out(@_) : Jifty::View::out_method(@_);
 }
 
 
@@ -125,10 +131,6 @@
                 path => undef,
                 @_);
 
-    if ($args{'scheme'}) {
-        $self->log->error("Jifty->web->url no longer accepts a 'scheme' argument");
-    }
-
     my $uri;
 
     # Try to get a host out of the environment, useful in remote testing.
@@ -165,6 +167,10 @@
       $uri->port($port);
     }
 
+    if ( defined $args{'scheme'} ) {
+        $uri->scheme( $args{'scheme'} );
+    }
+
     if (defined $args{path}) {
       my $path = $args{path};
       # strip off leading '/' because ->canonical provides one
@@ -299,18 +305,65 @@
 
 sub handle_request {
     my $self = shift;
-    die _( "No request to handle" ) unless Jifty->web->request;
+    die _("No request to handle") unless Jifty->web->request;
+
+    my ( $valid_actions, $denied_actions )
+        = $self->_validate_request_actions();
+
+    # In the case where we have a continuation and want to redirect
+    if ( $self->request->continuation_path && Jifty->web->request->argument('_webservice_redirect') ) {
+        # for continuation - perform internal redirect under webservices
+	$self->webservices_redirect($self->request->continuation_path);
+        return;
+    }
 
+    $self->request->save_continuation;
+
+    unless ( $self->request->just_validating ) {
+        $self->_process_valid_actions($valid_actions);
+        $self->_process_denied_actions($denied_actions);
+    }
+
+    # If there's a continuation call, don't do the rest of this
+    return if $self->response->success and $self->request->call_continuation;
+
+    $self->redirect if $self->redirect_required;
+    $self->request->do_mapping;
+}
+
+sub _process_denied_actions {
+    my $self           = shift;
+    my $denied_actions = shift;
+
+    for my $request_action (@$denied_actions) {
+        my $action = $self->new_action_from_request($request_action);
+        $action->deny( "Access Denied for " . ref($action) );
+        $self->response->result( $action->moniker => $action->result );
+    }
+}
+
+sub _validate_request_actions {
+        my $self = shift;
+        
     my @valid_actions;
+    my @denied_actions;
+
+
     for my $request_action ( $self->request->actions ) {
-        $self->log->debug("Found action ".$request_action->class . " " . $request_action->moniker);
+        $self->log->debug( "Found action "
+                . $request_action->class . " "
+                . $request_action->moniker );
         next unless $request_action->active;
         next if $request_action->has_run;
-        unless ( Jifty->api->is_allowed( $request_action->class ) ) {
-            $self->log->warn( "Attempt to call denied action '"
-                    . $request_action->class
-                    . "'" );
-            next;
+        unless ( $self->request->just_validating ) {
+            unless ( Jifty->api->is_allowed( $request_action->class ) ) {
+                $self->log->warn( "Attempt to call denied action '"
+                        . $request_action->class
+                        . "'" );
+                Carp::cluck;
+                push @denied_actions, $request_action;
+                next;
+            }
         }
 
         # Make sure we can instantiate the action
@@ -321,16 +374,21 @@
         # Try validating -- note that this is just the first pass; as
         # actions are run, they may fill in values which alter
         # validation of later actions
-        $self->log->debug("Validating action ".ref($action). " ".$action->moniker);
+        $self->log->debug( "Validating action " . ref($action) . " " . $action->moniker );
         $self->response->result( $action->moniker => $action->result );
         $action->validate;
 
         push @valid_actions, $request_action;
     }
-    $self->request->save_continuation;
+    
+    return (\@valid_actions, \@denied_actions);
 
-    unless ( $self->request->just_validating ) {
-        for my $request_action (@valid_actions) {
+}
+
+sub _process_valid_actions {
+    my  $self = shift;
+    my $valid_actions = shift;
+        for my $request_action (@$valid_actions) {
 
             # Pull the action out of the request (again, since
             # mappings may have affected parameters).  This
@@ -339,20 +397,26 @@
             # actions (Jifty::Request::Mapper)
             my $action = $self->new_action_from_request($request_action);
             next unless $action;
-            if ($request_action->modified) {
+            if ( $request_action->modified ) {
+
                 # If the request's action was changed, re-validate
-                $action->result(Jifty::Result->new);
-                $action->result->action_class(ref $action);
-                $self->response->result( $action->moniker => $action->result );
-                $self->log->debug("Re-validating action ".ref($action). " ".$action->moniker);
+                $action->result( Jifty::Result->new );
+                $action->result->action_class( ref $action );
+                $self->response->result(
+                    $action->moniker => $action->result );
+                $self->log->debug( "Re-validating action "
+                        . ref($action) . " "
+                        . $action->moniker );
                 next unless $action->validate;
             }
 
-            $self->log->debug("Running action ".ref($action). " ".$action->moniker);
+            $self->log->debug(
+                "Running action " . ref($action) . " " . $action->moniker );
             eval { $action->run; };
             $request_action->has_run(1);
 
             if ( my $err = $@ ) {
+
                 # Poor man's exception propagation; we need to get
                 # "LAST RULE" and "ABORT" exceptions back up to the
                 # dispatcher.  This is specifically for redirects from
@@ -362,7 +426,8 @@
                 $action->result->error(
                     Jifty->config->framework("DevelMode")
                     ? $err
-                    : _("There was an error completing the request.  Please try again later.")
+                    : _("There was an error completing the request.  Please try again later."
+                    )
                 );
             }
 
@@ -370,15 +435,8 @@
             # may have yielded.
             $self->request->do_mapping;
         }
-    }
-
-    # If there's a continuation call, don't do the rest of this
-    return if $self->response->success and $self->request->call_continuation;
-
-    $self->redirect if $self->redirect_required;
-    $self->request->do_mapping;
-}
 
+    }
 =head3 request [VALUE]
 
 Gets or sets the current L<Jifty::Request> object.
@@ -403,7 +461,9 @@
 
 =head3 new_action class => CLASS, moniker => MONIKER, order => ORDER, arguments => PARAMHASH
 
-Creates a new action (an instance of a subclass of L<Jifty::Action>). The named arguments passed to this method are passed on to the C<new> method of the action named in C<CLASS>.
+Creates a new action (an instance of a subclass of
+L<Jifty::Action>). The named arguments passed to this method are
+passed on to the C<new> method of the action named in C<CLASS>.
 
 =head3 Arguments
 
@@ -468,17 +528,6 @@
     $class = Jifty->api->qualify($class);
 
     my $loaded = Jifty::Util->require( $class );
-    $args{moniker} ||= ($loaded ? $class : 'Jifty::Action')->_generate_moniker;
-
-    my $action_in_request = $self->request->action( $args{moniker} );
-
-    # Fields explicitly passed to new_action take precedence over those passed
-    # from the request; we read from the request to implement "sticky fields".
-    #
-    if ( $action_in_request and $action_in_request->arguments ) {
-        $args{'request_arguments'} = $action_in_request->arguments;
-    }
-
     # The implementation class is provided by the client, so this
     # isn't a "shouldn't happen"
     return unless $loaded;
@@ -593,22 +642,53 @@
     }
 }
 
+=head3 webservices_redirect [TO]
+
+Handle redirection inside webservices call.  This is meant to be
+hooked by plugin that knows what to do with it.
+
+=cut
+
+sub webservices_redirect {
+    my ( $self, $to ) = @_;
+    # XXX: move to singlepage plugin
+    my ($spa) = Jifty->find_plugin('Jifty::Plugin::SinglePage') or return;
+
+    Jifty->web->request->remove_state_variable( 'region-'.$spa->region_name );
+    Jifty->web->request->add_fragment(
+        name      => $spa->region_name,
+        path      => $to,
+        arguments => {},
+        wrapper   => 0
+    );
+}
+
 =head3 redirect [TO]
 
 Redirect to the next page. If you pass this method a parameter, it
 redirects to that URL rather than B<next_page>.
 
 It creates a continuation of where you want to be, and then calls it.
-If you want to redirect to a parge with parameters, pass in a
+If you want to redirect to a page with parameters, pass in a
 L<Jifty::Web::Form::Clickable> object.
 
 =cut
 
 sub redirect {
     my $self = shift;
-    my $page = shift || $self->next_page || $self->request->path;
-    $page = Jifty::Web::Form::Clickable->new( url => $page )
-      unless ref $page and $page->isa("Jifty::Web::Form::Clickable");
+    my $redir_to = shift || $self->next_page || $self->request->path;
+
+    
+    my $page;
+
+    if ( ref $redir_to and $redir_to->isa("Jifty::Web::Form::Clickable")) {
+        $page = $redir_to;
+    } else {
+
+        $page = Jifty::Web::Form::Clickable->new();
+        #We set this after creation to ensure that plugins that massage clickables don't impact us
+        $page->url($redir_to );
+    }
 
     carp "Don't include GET parameters in the redirect URL -- use a Jifty::Web::Form::Clickable instead.  See L<Jifty::Web/redirect>" if $page->url =~ /\?/;
 
@@ -619,6 +699,9 @@
 
     # To submit a Jifty::Action::Redirect, we don't need to serialize a continuation,
     # unlike any other kind of actions.
+
+    my $redirect_to_url = '' ;
+
     if (  (grep { not $_->action_class->isa('Jifty::Action::Redirect') }
                 values %{ { $self->response->results } })
         or $self->request->state_variables
@@ -655,17 +738,34 @@
             response => $self->response,
             parent   => $self->request->continuation,
         );
-        $page = $page->url."?J:RETURN=" . $cont->id;
+        $redirect_to_url = $page->url."?J:RETURN=" . $cont->id;
     } else {
-        $page = $page->complete_url;
+        $redirect_to_url = $page->complete_url;
     }
-    $self->_redirect($page);
+    $self->_redirect($redirect_to_url);
 }
 
 sub _redirect {
     my $self = shift;
     my ($page) = @_;
 
+    # It's an experimental feature to support redirect within a
+    # region.
+    if ($self->current_region) { 
+        # If we're within a region stack, we don't really want to
+        # redirect. We want to redispatch.  Also reset the things
+        # applied on beofre.
+        local $self->{navigation} = undef;
+        local $self->{page_navigation} = undef;
+        $self->replace_current_region($page);
+        Jifty::Dispatcher::_abort;
+        return;
+    }
+
+    if (my $redir = Jifty->web->request->argument('_webservice_redirect')) {
+	push @$redir, $page;
+	return;
+    }
     # $page can't lead with // or it assumes it's a URI scheme.
     $page =~ s{^/+}{/};
 
@@ -678,7 +778,7 @@
 
     my $apache = Jifty->handler->apache;
 
-    $self->log->debug("Redirecting to $page");
+    $self->log->debug("Execing redirect to $page");
     # Headers..
     $apache->header_out( Location => $page );
     $apache->header_out( Status => 302 );
@@ -721,6 +821,10 @@
 sub tangent {
     my $self = shift;
 
+    if (@_ == 1  ) {
+        Jifty->log->error("Jifty::Web->tangent takes a paramhash. Perhaps you passed '".$_[0]."' , rather than 'url => ".$_[0]."'");
+        die; 
+    }
     my $clickable = Jifty::Web::Form::Clickable->new(
         returns        => { },
         preserve_state => 1,
@@ -969,25 +1073,38 @@
 
 sub include_css {
     my $self = shift;
-    
-    if ( Jifty->config->framework('DevelMode') ) {
+    my ($ccjs) = Jifty->find_plugin('Jifty::Plugin::CompressedCSSandJS');
+    if ( $ccjs && $ccjs->css_enabled ) {
+        $self->generate_css;
         $self->out(
-            '<link rel="stylesheet" type="text/css" '
-            . 'href="/static/css/main.css" />'
+            '<link rel="stylesheet" type="text/css" href="/__jifty/css/'
+            . __PACKAGE__->cached_css_digest . '.css" />'
         );
     }
     else {
-        $self->generate_css;
-    
         $self->out(
-            '<link rel="stylesheet" type="text/css" href="/__jifty/css/'
-            . __PACKAGE__->cached_css_digest . '.css" />'
+            '<link rel="stylesheet" type="text/css" '
+            . 'href="/static/css/main.css" />'
         );
     }
     
     return '';
 }
 
+=head3 add_css FILE1, FILE2, ...
+
+Pushes files onto C<Jifty->web->css_files>
+
+=cut
+
+sub add_css {
+    my $self = shift;
+    Jifty->web->css_files([
+        @{ Jifty->web->css_files },
+        @_
+    ]);
+}
+
 =head3 generate_css
 
 Checks if the compressed CSS is generated, and if it isn't, generates
@@ -997,35 +1114,21 @@
 
 sub generate_css {
     my $self = shift;
-    
+
     if (not defined __PACKAGE__->cached_css_digest
             or Jifty->config->framework('DevelMode'))
     {
         Jifty->log->debug("Generating CSS...");
         
-        my $app   = File::Spec->catdir(
-                        Jifty->config->framework('Web')->{'StaticRoot'},
-                        'css'
-                    );
-
-        my $jifty = File::Spec->catdir(
-                        Jifty->config->framework('Web')->{'DefaultStaticRoot'},
-                        'css'
-                    );
-
-        my $file = Jifty::Util->absolute_path(
-                        File::Spec->catpath( '', $app, 'main.css' )
-                   );
-
-        if ( not -e $file ) {
-            $file = Jifty::Util->absolute_path(
-                         File::Spec->catpath( '', $jifty, 'main.css' )
-                    );
-        }
+        my @roots = map { Jifty::Util->absolute_path( File::Spec->catdir( $_, 'css' ) ) }
+                        Jifty->handler->view('Jifty::View::Static::Handler')->roots;
 
-        CSS::Squish->roots( Jifty::Util->absolute_path( $app ), $jifty );
+        CSS::Squish->roots( @roots );
         
-        my $css = CSS::Squish->concatenate( $file );
+        my $css = CSS::Squish->concatenate(
+            map { CSS::Squish->_resolve_file( $_, @roots ) }
+                @{ $self->css_files }
+        );
 
         __PACKAGE__->cached_css( $css );
         __PACKAGE__->cached_css_digest( md5_hex( $css ) );
@@ -1050,109 +1153,70 @@
 
 However if you want to include other javascript libraries you need to
 add them to the javascript_libs array of your application.  Do this in
-the C<start> sub of your main application class.  For example if your application is Foo then in L<lib/Foo.pm>
+the C<start> sub of your main application class.  For example if your
+application is Foo then in L<lib/Foo.pm>
 
  sub start {
-   Jifty->web->javascript_libs([
- 			       @{ Jifty->web->javascript_libs },
- 			       "yourJavascriptLib.js",
- 			      ]);
+     Jifty->web->add_javascript(qw( jslib1.js jslib2.js ) );
  }
 
+The L<add_javascript> method will append the files to javascript_libs.
+If you need a different order, you'll have to massage javascript_libs
+directly.
+
 Jifty will look for javascript libraries under share/web/static/js/ by
-default.
+default as well as any plugin static roots.
 
 =cut
 
 sub include_javascript {
     my $self  = shift;
-    
-    if ( Jifty->config->framework('DevelMode') ) {
-        for my $file ( @{ __PACKAGE__->javascript_libs } ) {
-            $self->out(
-                qq[<script type="text/javascript" src="/static/js/$file"></script>\n]
-            );
-        }
+
+    for my $url ( @{ __PACKAGE__->external_javascript_libs } ) {
+        $self->out(
+            qq[<script type="text/javascript" src="$url"></script>\n]
+        );
     }
-    else {
-        $self->generate_javascript;
-    
+
+    # if there's no trigger, 0 is returned.  if aborted/handled, undef
+    # is returned.
+    defined $self->call_trigger('include_javascript', @_) or return '';
+
+    for my $file ( @{ __PACKAGE__->javascript_libs } ) {
         $self->out(
-            qq[<script type="text/javascript" src="/__jifty/js/]
-            . __PACKAGE__->cached_javascript_digest . qq[.js"></script>]
+            qq[<script type="text/javascript" src="/static/js/$file"></script>\n]
         );
     }
-    
+
     return '';
 }
 
-=head3 generate_javascript
+=head3 add_javascript FILE1, FILE2, ...
 
-Checks if the compressed JS is generated, and if it isn't, generates
-and caches it.
+Pushes files onto C<Jifty->web->javascript_libs>
 
 =cut
 
-sub generate_javascript {
+sub add_javascript {
     my $self = shift;
-    
-    if (not defined __PACKAGE__->cached_javascript_digest
-            or Jifty->config->framework('DevelMode'))
-    {
-        Jifty->log->debug("Generating JS...");
-        
-        my @roots = (
-            Jifty::Util->absolute_path(
-                File::Spec->catdir(
-                    Jifty->config->framework('Web')->{'StaticRoot'},
-                    'js'
-                )
-            ),
-
-            Jifty::Util->absolute_path(
-                File::Spec->catdir(
-                    Jifty->config->framework('Web')->{'DefaultStaticRoot'},
-                    'js'
-                )
-            ),
-        );
-        
-        my $js = "";
+    Jifty->web->javascript_libs([
+        @{ Jifty->web->javascript_libs },
+        @_
+    ]);
+}
 
-        for my $file ( @{ __PACKAGE__->javascript_libs } ) {
-            my $include;
-        
-            for my $root (@roots) {
-                my @spec = File::Spec->splitpath( $root, 1 );
-                my $path = File::Spec->catpath( @spec[0,1], $file );
-                
-                if ( -e $path ) {
-                    $include = $path;
-                    last;
-                }
-            }
+=head3 add_external_javascript URL1, URL2, ...
 
-            if ( defined $include ) {
-                my $fh;
+Pushes urls onto C<Jifty->web->external_javascript_libs>
 
-                if ( open $fh, '<', $include ) {
-                    $js .= "/* Including '$file' */\n\n";
-                    $js .= $_ while <$fh>;
-                    $js .= "\n/* End of '$file' */\n\n";
-                }
-                else {
-                    $js .= "\n/* Unable to open '$file': $! */\n";
-                }
-            }
-            else {
-                $js .= "\n/* Unable to find '$file' */\n";
-            }
-        }
+=cut
 
-        __PACKAGE__->cached_javascript( $js );
-        __PACKAGE__->cached_javascript_digest( md5_hex( $js ) );
-        __PACKAGE__->cached_javascript_time( time );
-    }
+sub add_external_javascript {
+    my $self = shift;
+    Jifty->web->external_javascript_libs([
+        @{ Jifty->web->external_javascript_libs },
+        @_
+    ]);
 }
 
 =head2 STATE VARIABLES
@@ -1259,6 +1323,22 @@
     $region->render;
 }
 
+
+=head3 replace_current_region PATH
+
+Replaces the current region with a new region and renders it Returns undef if there's no current region
+
+=cut
+
+sub replace_current_region {
+    my $self = shift;
+    my $path = shift;
+    return undef unless (my $region = $self->current_region);
+    $region->force_path($path);
+    $region->render;
+}
+
+
 =head3 current_region
 
 Returns the name of the current L<Jifty::Web::PageRegion>, or undef if

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form.pm	Sun Jul 22 21:13:55 2007
@@ -7,6 +7,12 @@
 
 __PACKAGE__->mk_accessors(qw(actions printed_actions name call is_open disable_autocomplete target submit_to));
 
+=head1 NAME
+
+Jifty::Web::Form - Tools for rendering and dealing with HTML forms
+
+=head1 METHODS
+
 =head2 new ARGS
 
 Creates a new L<Jifty::Web::Form>.  Arguments:
@@ -217,8 +223,18 @@
 
 sub submit {
     my $self = shift;
+    my %args = (submit => undef,
+                _form => $self,
+                @_);
+
+    my @submit = ref($args{'submit'}) eq 'ARRAY' ? @{$args{'submit'}} : $args{'submit'};
+    if ($self->actions->{'next_page'} && $submit[0] && ! grep {$_->moniker eq 'next_page' } @submit)  {
+        push @submit, $self->actions->{'next_page'};
+        $args{'submit'} = \@submit;
+    }
+
 
-    my $button = Jifty::Web::Form::Clickable->new(submit => undef, @_)->generate;
+    my $button = Jifty::Web::Form::Clickable->new(%args)->generate;
     Jifty->web->out(qq{<div class="submit_button">});
     $button->render_widget;
     Jifty->web->out(qq{</div>});

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Clickable.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Clickable.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Clickable.pm	Sun Jul 22 21:13:55 2007
@@ -2,6 +2,7 @@
 use strict;
 
 package Jifty::Web::Form::Clickable;
+use Class::Trigger;
 
 =head1 NAME
 
@@ -143,6 +144,8 @@
         @_,
     );
 
+    $class->call_trigger('before_new', \%args);
+
     $args{render_as_button} = delete $args{as_button};
     $args{render_as_link}   = delete $args{as_link};
 
@@ -452,11 +455,25 @@
           escape_label => $self->escape_label,
           url          => $self->complete_url,
           target       => $self->target,
+          continuation => $self->_continuation,
           @_ }
     );
     return $link;
 }
 
+sub _continuation {
+    # continuation info used by the update() call on client side
+    my $self = shift;
+    if ($self->call) {
+	return { 'type' => 'call', id => $self->call };
+    }
+    if ($self->returns) {
+	return { 'create' => $self->url };
+    }
+
+    return {};
+}
+
 =head2 as_button
 
 Returns the clickable as a L<Jifty::Web::Form::Field::InlineButton>,
@@ -473,6 +490,7 @@
     my $field = Jifty::Web::Form::Field->new(
         { %$args,
           type => 'InlineButton',
+          continuation => $self->_continuation,
           @_ }
     );
     my %parameters = $self->post_parameters;

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Element.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Element.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Element.pm	Sun Jul 22 21:13:55 2007
@@ -149,8 +149,8 @@
 
 =cut
 
-sub accessors { shift->handlers, qw(class key_binding key_binding_label id label tooltip) }
-__PACKAGE__->mk_accessors(qw(_onclick class key_binding key_binding_label id label tooltip));
+sub accessors { shift->handlers, qw(class key_binding key_binding_label id label tooltip continuation) }
+__PACKAGE__->mk_accessors(qw(_onclick class key_binding key_binding_label id label tooltip continuation));
 
 =head2 new PARAMHASH OVERRIDE
 
@@ -236,7 +236,10 @@
         next unless $value;
 
         my @fragments;
-        my %actions;    # Maps actions => disable?
+            # if $actions is undef, that means we're submitting _all_ actions in the clickable
+            # if $actions is defined but empty, that means we're submitting no actions
+            # if $actions is not empty, we're submitting those actions
+        my $actions = {};    # Maps actions => disable?
         my $confirm;
         my $beforeclick;
 
@@ -245,11 +248,14 @@
             my %args;
 
             # Submit action
-            if ( $hook->{submit} ) {
-                my $disable = exists $hook->{disable} ? $hook->{disable} : 1;
+          
+            
+            if ( exists $hook->{submit} ) {
+                $actions = undef;
+                my $disable_form_on_click = exists $hook->{disable} ? $hook->{disable} : 1;
                 # Normalize to 1/0 to pass to JS
-                $disable = $disable ? 1 : 0;
-                $actions{$_} = $disable for (@{ $hook->{submit} }); 
+                $disable_form_on_click = $disable_form_on_click ? 1 : 0;
+                $actions->{$_} = $disable_form_on_click for (@{ $hook->{submit} || [] }); 
             }
 
             $hook->{region} ||= Jifty->web->qualified_region;
@@ -317,9 +323,10 @@
         }
 
         my $string = join ";", (grep {not ref $_} (ref $value eq "ARRAY" ? @{$value} : ($value)));
-        if (@fragments or %actions) {
+        if (@fragments or (!$actions || %$actions)) {
 
-            my $update = Jifty->web->escape("update( ". Jifty::JSON::objToJson( {actions => \%actions, fragments => \@fragments }, {singlequote => 1}) .", this );");
+            my $update = Jifty->web->escape("update( ". Jifty::JSON::objToJson( {actions => $actions, fragments => \@fragments, continuation => $self->continuation }, {singlequote => 1}) .", this );");
+            $string .= 'if(event.ctrlKey||event.metaKey||event.altKey||event.shiftKey) return true; ';
             $string .= $self->javascript_preempt ? "return $update" : "$update; return true;";
         }
         if ($confirm) {

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field.pm	Sun Jul 22 21:13:55 2007
@@ -79,8 +79,9 @@
 
     # If they key and/or value imply that this argument is going to be
     # a mapped argument, then do the mapping and mark the field as hidden.
+    # but ignore that if the field is a container in the model
     my ($key, $value) = Jifty::Request::Mapper->query_parameters($self->input_name, $self->current_value);
-    if ($key ne $self->input_name) {
+    if ($key ne $self->input_name && !$self->action->arguments->{$self->name}{container}) {
         Jifty::Util->require('Jifty::Web::Form::Field::Hidden');
         bless $self, "Jifty::Web::Form::Field::Hidden";
         $self->input_name($key);

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Button.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Button.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Button.pm	Sun Jul 22 21:13:55 2007
@@ -9,7 +9,7 @@
 
 =head1 NAME
 
-Jifty::Web::Form::Field::Button
+Jifty::Web::Form::Field::Button - Add buttons to your forms
 
 =cut
 

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Checkbox.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Checkbox.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Checkbox.pm	Sun Jul 22 21:13:55 2007
@@ -6,6 +6,12 @@
 use base qw/Jifty::Web::Form::Field/;
 __PACKAGE__->mk_accessors(qw/checked value/);
 
+=head1 NAME
+
+Jifty::Web::Form::Field::Checkbox - Add checkboxes to your forms
+
+=head1 METHODS
+
 =head2 accessors
 
 Provide C<checked> and C<value> accessors, in addition to

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Combobox.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Combobox.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Combobox.pm	Sun Jul 22 21:13:55 2007
@@ -5,6 +5,12 @@
 
 use base qw/Jifty::Web::Form::Field/;
 
+=head1 NAME
+
+Jifty::Web::Form::Field::Combobox - Add comboboxes to your forms
+
+=head1 METHODS
+
 =head2 render_widget
 
 Renders the select widget.

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Date.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Date.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Date.pm	Sun Jul 22 21:13:55 2007
@@ -5,6 +5,12 @@
 
 use base qw/Jifty::Web::Form::Field/;
 
+=head1 NAME
+
+Jifty::Web::Form::Field::Date - Add date pickers to your forms
+
+=head1 METHODS
+
 =head2 classes
 
 Output date fields with the class 'date'

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Hidden.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Hidden.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Hidden.pm	Sun Jul 22 21:13:55 2007
@@ -5,6 +5,12 @@
 
 use base qw/Jifty::Web::Form::Field/;
 
+=head1 NAME
+
+Jifty::Web::Form::Field::Hidden - Add hidden fields to your forms
+
+=head1 METHODS
+
 =head2 type
 
 The HTML input type is C<hidden>.

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/InlineButton.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/InlineButton.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/InlineButton.pm	Sun Jul 22 21:13:55 2007
@@ -5,6 +5,11 @@
 
 use base qw/Jifty::Web::Form::Field::Button/;
 
+=head1 NAME
+
+Jifty::Web::Form::Field::InlineButton - Add buttons without a form
+
+=head1 METHODS
 
 =head2 render
 

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Password.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Password.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Password.pm	Sun Jul 22 21:13:55 2007
@@ -5,6 +5,12 @@
 
 use base qw/Jifty::Web::Form::Field/;
 
+=head1 NAME
+
+Jifty::Web::Form::Field::Password - Add a password field to your forms
+
+=head1 METHODS
+
 =head2 type
 
 The HTML input type is C<password>.

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Radio.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Radio.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Radio.pm	Sun Jul 22 21:13:55 2007
@@ -5,6 +5,12 @@
 
 use base qw/Jifty::Web::Form::Field/;
 
+=head1 NAME
+
+Jifty::Web::Form::Field::Radio - Add a radio button to your forms
+
+=head1 METHODS
+
 =head2 render_widget
 
 Renders the whole radio button collection.

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/ResetButton.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/ResetButton.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/ResetButton.pm	Sun Jul 22 21:13:55 2007
@@ -5,6 +5,11 @@
 
 use base qw/Jifty::Web::Form::Field::InlineButton/;
 
+=head1 NAME
+
+Jifty::Web::Form::Field::ResetButton - Add a reset button to your forms
+
+=head1 METHODS
 
 =head2 render_widget
 

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Select.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Select.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Select.pm	Sun Jul 22 21:13:55 2007
@@ -5,6 +5,12 @@
 
 use base qw/Jifty::Web::Form::Field/;
 
+=head1 NAME
+
+Jifty::Web::Form::Field::Select - Add a list/popup menu control to your forms
+
+=head1 METHODS
+
 =head2 render_widget
 
 Renders the select widget.

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Text.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Text.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Text.pm	Sun Jul 22 21:13:55 2007
@@ -8,6 +8,8 @@
 
 Jifty::Web::Form::Field::Text - Renders as a small text field
 
+=head1 METHODS
+
 =cut
 
 our $VERSION = 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Textarea.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Textarea.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Textarea.pm	Sun Jul 22 21:13:55 2007
@@ -7,6 +7,12 @@
 
 __PACKAGE__->mk_accessors(qw(rows cols));
 
+=head1 NAME
+
+Jifty::Web::Form::Field::Textarea - Add a multiline text field to your forms
+
+=head1 METHODS
+
 =head2 accessors
 
 Provide C<rows> and C<cols> accessors, in addition to

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Unrendered.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Unrendered.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Unrendered.pm	Sun Jul 22 21:13:55 2007
@@ -5,6 +5,12 @@
 
 use base qw/Jifty::Web::Form::Field/;
 
+=head1 NAME
+
+Jifty::Web::Form::Field::Unrendered - Handle unrendered fields
+
+=head1 METHODS
+
 =head2 render
 
 Don't render anything. For one reason or another, this form field should never, ever be rendered, perhaps

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Upload.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Upload.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Field/Upload.pm	Sun Jul 22 21:13:55 2007
@@ -44,4 +44,15 @@
     '';
 }
 
+=head2 classes
+
+Add 'upload' to the rest of the classes
+
+=cut
+
+sub classes {
+    my $self = shift;
+    return join(' ', 'upload', ($self->SUPER::classes));
+}
+
 1;

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Form/Link.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Form/Link.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Form/Link.pm	Sun Jul 22 21:13:55 2007
@@ -101,12 +101,12 @@
 
     my $tooltip = $self->tooltip;
     $tooltip = Jifty->web->escape( $tooltip )
-        if ( $tooltip and $self->escape_label );
+        if ( defined $tooltip and $self->escape_label );
 
     Jifty->web->out(qq(<a));
     Jifty->web->out(qq( id="@{[$self->id]}"))         if $self->id;
     Jifty->web->out(qq( class="@{[$self->class]}"))   if $self->class;
-    Jifty->web->out(qq( title="@{[$self->tooltip]}")) if $tooltip;
+    Jifty->web->out(qq( title="@{[$tooltip]}"))       if defined $tooltip;
     Jifty->web->out(qq( target="@{[$self->target]}")) if $self->target;
     Jifty->web->out(qq( accesskey="@{[$self->key_binding]}")) if $self->key_binding;
     Jifty->web->out(qq( href="@{[Jifty->web->escape($self->url)]}"));

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Menu.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Menu.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Menu.pm	Sun Jul 22 21:13:55 2007
@@ -6,6 +6,12 @@
 
 __PACKAGE__->mk_accessors(qw(label parent sort_order link target escape_label class));
 
+=head1 NAME
+
+Jifty::Web::Menu - Handle the API for menu navigation
+
+=head1 METHODS
+
 =head2 new PARAMHASH
 
 Creates a new L<Jifty::Web::Menu> object.  Possible keys in the

Modified: jifty/branches/autoversioning/lib/Jifty/Web/PageRegion.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/PageRegion.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/PageRegion.pm	Sun Jul 22 21:13:55 2007
@@ -215,7 +215,7 @@
             $self->argument($2 => $value);
         }
         if ($key =~ /^region-(.*)$/ and $1 eq $self->qualified_name and $value ne $self->default_path) {
-            $self->path($value);
+            $self->path(URI::Escape::uri_unescape($value));
         }
 
         # We should always inherit the state variables from the uplevel request.
@@ -298,7 +298,7 @@
 sub render_as_subrequest {
     my ($self, $out_method, $arguments, $enable_actions) = @_;
 
-    my $orig_out = Jifty->handler->mason->interp->out_method || \&Jifty::View::Mason::Handler::out_method;
+    my $orig_out = Jifty->handler->mason->interp->out_method || Jifty::View->can('out_method');
 
     Jifty->handler->mason->interp->out_method($out_method);
 
@@ -310,6 +310,17 @@
     $subrequest->path( $self->path );
     $subrequest->top_request( Jifty->web->request->top_request );
 
+    if ($self->path =~ m/\?/) {
+	# XXX: this only happens if we are redirect within region AND
+	# with continuation, which is already taken care of by the
+	# clone.
+	my ($path, $arg) = split(/\?/, $self->path, 2);
+	$subrequest->path( $path );
+	my %args = (map { split /=/, $_ } split /&/, $arg);
+	if ($args{'J:C'}) {
+	    $subrequest->continuation($args{'J:C'});
+	}
+    }
     # Remove all of the actions
     unless ($enable_actions) {
 	$_->active(0) for ($subrequest->actions);

Modified: jifty/branches/autoversioning/lib/Jifty/Web/Session.pm
==============================================================================
--- jifty/branches/autoversioning/lib/Jifty/Web/Session.pm	(original)
+++ jifty/branches/autoversioning/lib/Jifty/Web/Session.pm	Sun Jul 22 21:13:55 2007
@@ -10,7 +10,14 @@
 
 Jifty::Web::Session - A Jifty session handler
 
-=cut
+=head1 SYNOPSIS
+
+In your F<etc/config.yml> (optional):
+
+  framework:
+    Web:
+      # The default ($PORT is replaced by the port the app is running on)
+      SessionCookieName: JIFTY_SID_$PORT
 
 =head2 new
 
@@ -22,12 +29,13 @@
     my $class = shift;
 
     my $session_class = Jifty->config->framework('Web')->{'SessionClass'};
+    my $cookie_name   = Jifty->config->framework('Web')->{'SessionCookieName'};
     if ($session_class and $class ne $session_class) {
         Jifty::Util->require( $session_class );
         return $session_class->new(@_);
     }
     else {
-        return bless {}, $class;
+        return bless { _cookie_name => $cookie_name }, $class;
     }
 }
 
@@ -276,8 +284,6 @@
 
     my $cookie_name = $self->cookie_name;
     my %cookies     = CGI::Cookie->fetch();
-    my $session_id
-        = $cookies{$cookie_name} ? $cookies{$cookie_name}->value() : undef;
     my $cookie = new CGI::Cookie(
         -name    => $cookie_name,
         -value   => $self->id,
@@ -302,7 +308,9 @@
 
 sub cookie_name {
     my $self = shift;
-    my $cookie_name = "JIFTY_SID_" . ( $ENV{'SERVER_PORT'} || 'NOPORT' );
+    my $cookie_name = $self->{'_cookie_name'};
+    my $port = ( $ENV{'SERVER_PORT'} || 'NOPORT' );
+    $cookie_name =~ s/\$PORT/$port/g;
     return ($cookie_name);
 }
 

Added: jifty/branches/autoversioning/plugins/CodePress/Makefile.PL
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/Makefile.PL	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,8 @@
+use inc::Module::Install;
+name('Jifty-Plugin-CodePress');
+version('0.02');
+requires('Jifty' => '0.70422');
+
+install_share;
+
+WriteAll;

Added: jifty/branches/autoversioning/plugins/CodePress/doc/index.html
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/doc/index.html	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,436 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html>
+<head>
+	<title>CodePress - Real Time Syntax Highlighting Editor written in JavaScript</title>
+
+	<style>
+	body {color:#000;background-color:white;font:15px georgia, "Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif; letter-spacing:0.01em;margin:15px;}
+	p {margin:0 0 15px 0;}
+	a,a:visited {color:#7f0055;}
+	select {background:#ffffe1;}
+	button {margin-top:5px;}
+	button.actions {width:171px;font-family:arial;}
+	h1 {color:#7f0055;margin:0;padding:0;font-size:42px;font-weight:normal;}
+	h1 a {text-decoration:none;}
+	h2 {margin:0;}
+	h2 a {text-decoration:none;font-weight:normal;font-size:22px;color:black !important;}
+	h3 {font-size:20px;font-weight:normal;padding:0;margin:25px 0 5px 0;color:#7f0055;font-weight:bold;border-bottom:2px dotted #d8d8d8;}
+	h4 {font-size:18px;font-weight:normal;z-index:0;}	
+	code {color:#0080c0;font-size:13px;font-weight:bold;}
+	ol, ul {padding:5px 0 5px 25px;margin:0;}
+	ol li, ul li {margin:8px 0 8px 0;}
+	
+	#logo {text-align:center;background-color:#d6d6d6;padding:10px;-moz-border-radius:5px;border:1px solid silver;}
+	#container {width:700px;margin:20px auto;padding:25px;border:3px solid #d9d9d9;-moz-border-radius:10px;background:#f8f8f8;}
+	#languages {margin:5px 0;}
+	
+	#menu {width:100%;background:#7f0055;-moz-border-radius:4px;}
+	#menu a {font:bold 17px georgia;color:white;padding:4px;display:block;border-left:1px solid white;text-align:center;text-decoration:none;}
+	#menu a:hover {background:#b9669e;} 
+
+	.hidden-code {display:none;}
+	.copycode {border:1px dotted gray;padding:10px;background:white;font-family:monospace;color:gray}
+	</style>
+
+</head>
+
+<body>
+<div id="container">
+
+<div id="logo">
+	<h1><a href="http://codepress.org/">CodePress</a></h1>
+	<h2><a href="http://codepress.org/">Online Real Time Syntax Highlighting Editor</a></h2>
+</div>
+
+<br />
+
+<table cellpadding="0" cellspacing="0" id="menu">
+<tr>
+	<td>
+		<a href="http://www.codepress.org/index.php">Home/Download</a>
+	</td>
+	<td>
+		<a href="http://www.codepress.org/install.php">&nbsp;&nbsp;Install&nbsp;&nbsp;</a>
+	</td>
+	<td>
+		<a href="http://www.codepress.org/to-do.php">&nbsp;&nbsp;To-do&nbsp;&nbsp;</a>
+	</td>
+	<td>
+		<a href="http://www.codepress.org/about.php" id="about">&nbsp;&nbsp;About&nbsp;&nbsp;</a>
+	</td>
+</tr>
+</table>
+
+<h4>
+	CodePress is web-based source code editor with syntax highlighting written in JavaScript that colors text in real time while it's being typed in the browser.
+</h4>
+	
+<p>
+	Go to <strong><a href="http://codepress.org/">http://codepress.org/</a></strong> for updates.
+</p>
+
+<h3>Demo</h3>
+<div id="languages">
+	<em>choose example in:</em> 
+	<button onclick="cp1.edit('cp-php','php')">PHP</button> 
+	<button onclick="cp1.edit('cp-javascript','javascript')">JavaScript</button> 
+	<button onclick="cp1.edit('cp-java','java')">Java</button>
+	<button onclick="cp1.edit('cp-perl','perl')">Perl</button>
+	<button onclick="cp1.edit('cp-sql','sql')">SQL</button>	
+	<button onclick="cp1.edit('cp-html','html')">HTML</button> 
+	<button onclick="cp1.edit('cp-css','css')">CSS</button> 	
+</div>
+
+<textarea id="cp1" class="codepress php" style="width:700px;height:300px;" wrap="off">
+<?php
+// Very simple implementation of server side script
+
+if(isset($_GET['file'])) {
+	$file = basename($_GET['file']);
+	$full_file = $path['server'].'/'.$path['webdocs'].'/'.$path['files']."/".$file;
+	if(file_exists($full_file)) {
+		$code = file_get_contents($full_file);
+		$code = preg_replace("/>/","&amp;gt;",$code);
+		$code = preg_replace("/</","&amp;lt;",$code);
+		$language = getLanguage($file);
+	}
+}
+?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+	<title>CodePress - Real Time Syntax Highlighting Editor written in JavaScript</title>
+	<link type="text/css" href="languages/codepress-<?=$language?>.css" rel="stylesheet" id="cp-lang-style" />
+	<script type="text/javascript" src="codepress.js"></script>
+	<script type="text/javascript">
+		CodePress.language = '<?=$language?>';
+	</script>
+</head>
+<body id="ffedt"><pre id="ieedt"><?=$code?></pre></body>
+</html>
+</textarea>
+
+<br /><br />
+
+<textarea id="codepress2" class="codepress javascript linenumbers-off" style="width:700px;height:200px;" wrap="off">
+//set language
+this.setLanguage = function() {
+	if(arguments[0]) {
+		language = (typeof(Content.languages[arguments[0]])!='undefined') ? arguments[0] : this.setLanguage();
+		cpLanguage.innerHTML = Content.languages[language].name;
+		if(cpBody.document.designMode=='on') cpBody.document.designMode = 'off';
+		CodePress.loadScript(cpBody.document, '../languages/'+language+'.js', function () { cpBody.CodePress.syntaxHighlight('init'); })
+		cpBody.document.getElementById('cp-lang-style').href = '../languages/'+language+'.css';
+		this.hideMenu();
+	}
+	else {
+		var extension = filename.replace(/.*\.([^\.]+)$/,'$1');
+		var aux = false;
+		for(lang in Content.languages) {
+			extensions = ','+Content.languages[lang].extensions+',';
+			if(extensions.match(','+extension+',')) aux = lang;
+		}
+		language = (aux) ? aux : 'generic';
+	}
+}
+</textarea>
+
+<p>
+	<button class="actions" onclick="alert(codepress2.getCode())">get code from editor</button>
+	<button class="actions" onclick="codepress2.toggleEditor()">turn on/off CodePress</button>
+	<button class="actions" onclick="codepress2.toggleLineNumbers()">show/hide line numbers</button>
+	<button class="actions" onclick="codepress2.toggleAutoComplete()">turn on/off auto-complete</button>
+	<button class="actions" onclick="codepress2.toggleReadOnly()">turn on/off read only</button>
+</p>
+
+
+
+<h3>Installation</h3>
+<ol>
+	<li>
+		<p>
+			<a href="http://codepress.org/">Download</a> and uncompress CodePress under a directory inside your webserver.<br>
+			Example:<strong> http://yourserver/codepress/</strong><br />
+			Since CodePress is pure JavaScript and HTML, you can also test it without a webserver.
+		</p>
+	</li>
+	<li>
+		<p>
+			Insert CodePress script somewhere in your page inside the <code>&lt;head&gt;</code> or above the <code>&lt;/body&gt;</code> tag.
+		</p>
+	
+		<p class="copycode">
+			&lt;script src="/codepress/codepress.js" type="text/javascript"&gt;&lt;/script&gt;
+		</p>
+	</li>
+	
+	<li>
+		<p>
+			Add the <code>&lt;textarea&gt;</code> tag to the place on your page you want CodePress to appear. CodePress will inherit the width and height of your textarea.
+			When the page loads, it will automatically replace your textarea with a CodePress window.
+		</p>
+		<p class="copycode">
+			&lt;textarea id="myCpWindow" class="codepress javascript linenumbers-off"&gt;<br />
+			&nbsp;&nbsp;&nbsp;// your code here<br />
+			&lt;/textarea&gt;
+		</p>
+		<ul>
+			<li>
+				The <code>javascript</code> portion of the class="" means that the language being edited is JavaScript.
+			</li>
+			<li>
+				The <code>codepress</code> portion of the class="" is mandatory and indicates a textarea to be replaced for a CodePress window.
+			</li>
+			<li>
+				Other class options are <code>linenumbers-off</code>, <code>autocomplete-off</code> and <code>readonly-on</code>.
+			</li>			
+			<li>
+				Careful not to use the same id for two different CodePress windows (<code>&lt;textarea id="<strong>xx</strong>"...&gt;</code>)
+			</li>
+		</ul>
+
+	</li>
+</ol>
+
+<h3>You also can...</h3>
+<ol>
+	<li>
+		Open/edit code from a different textarea.<br />
+		Example: <code>textarea_id.edit('other_textarea_id','language')</code><br>
+	</li>
+	<li>
+		Get code from CodePress window.<br />
+		Example: <code>textarea_id.getCode()</code><br>
+	</li>
+	<li>
+		Turn on/off CodePress editor and return to the regular textarea.<br />
+		Example: <code>textarea_id.toggleEditor()</code><br>
+	</li>
+	<li>
+		Turn on/off line numbers.<br />
+		Example: <code>textarea_id.toggleLineNumbers()</code><br>
+	</li>
+	<li>
+		Turn on/off read only.<br />
+		Example: <code>textarea_id.toggleReadOnly()</code><br>
+	</li>
+	<li>
+		Turn on/off auto-complete.<br />
+		Example: <code>textarea_id.toggleAutoComplete()</code><br>
+	</li>
+	
+</ol>
+
+<!-- p>
+	You may want to use [id].getCode() to get the content code from CodePress window and save it to your server since CodePress only edit files and do not save them.
+</p>
+<p>
+	You may also want to open files from server. You'll have to write a server side script and replace the JavaScript call on codepress.js from codepress.html to codepress.php (if your server side language is PHP, of course).
+</p -->
+
+<h3>License</h3>
+<p>
+	CodePress is distributed under the <a href="http://www.opensource.org/licenses/lgpl-license.php">LGPL</a>. If your software is <a href="http://www.gnu.org/philosophy/license-list.html#GPLCompatibleLicenses">compatible</a> with this licence or it is under <a href="http://creativecommons.org/">Creative Commons</a>, you can use it as you want. Just keep the credits somewhere around.
+</p>
+
+
+</div><!--/container-->
+
+
+
+<!-- hidden codes for loading -->
+<textarea id="cp-php" class="hidden-code">
+<?php
+// Very simple implementation of server side script
+
+if(isset($_GET['file'])) {
+	$file = basename($_GET['file']);
+	$full_file = $path['server'].'/'.$path['webdocs'].'/'.$path['files']."/".$file;
+	if(file_exists($full_file)) {
+		$code = file_get_contents($full_file);
+		$code = preg_replace("/>/","&amp;gt;",$code);
+		$code = preg_replace("/</","&amp;lt;",$code);
+		$language = getLanguage($file);
+	}
+}
+?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+	<title>CodePress - Real Time Syntax Highlighting Editor written in JavaScript</title>
+	<link type="text/css" href="languages/codepress-<?=$language?>.css" rel="stylesheet" id="cp-lang-style" />
+	<script type="text/javascript" src="codepress.js"></script>
+	<script type="text/javascript">
+		CodePress.language = '<?=$language?>';
+	</script>
+</head>
+<body id="ffedt"><pre id="ieedt"><?=$code?></pre></body>
+</html>
+</textarea>
+
+<textarea id="cp-javascript" class="hidden-code">
+CodePress = function(obj) {
+	var self = document.createElement('iframe');
+	self.textarea = obj;
+	self.textarea.disabled = true;
+	self.style.height = self.textarea.clientHeight +'px';
+	self.style.width = self.textarea.clientWidth +'px';
+	
+	self.initialize = function() {
+		self.editor = self.contentWindow.CodePress;
+		self.editor.body = self.contentWindow.document.getElementsByTagName('body')[0];
+		self.editor.setCode(self.textarea.value);
+		self.editor.syntaxHighlight('init');
+	}
+	
+	self.edit = function(id,language) {
+		self.language = (language) ? language : self.textarea.className.replace(/ ?codepress ?/,'');
+		self.src = cpPath+'modules/codepress.html?engine='+self.getEngine()+'&language='+self.language;
+		if(self.attachEvent) self.attachEvent('onload',self.initialize);
+		else self.addEventListener('load',self.initialize,false);
+	}
+}
+</textarea>
+
+
+<textarea id="cp-java" class="hidden-code">
+import java.io.FileFilter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * Project ECCO - File manager class
+ * @author Fernando M.A.d.S.
+ */
+public class FileManager extends HttpServlet {
+
+	private static final long serialVersionUID = 1L;
+	private static String login = "feanndor"; // session var should come here
+	private static String usersPath = System.getProperty("user.dir")+File.separator+"htdocs"+File.separator+"ecco"+File.separator+"users"+File.separator;
+	private static File dir = new File(usersPath+login+File.separator);
+	static boolean existDirectories = false;
+	static int isDirectory = 0;
+
+	public FileFilter filterFiles(File dir) {
+		return (new FileFilter() {
+			public boolean accept(File pathname) {
+				return !(pathname.isDirectory());
+			}
+		});
+	}
+}
+</textarea>
+
+<textarea id="cp-perl" class="hidden-code">
+#!/usr/bin/perl      
+# The first line of the script envokes Perl 
+
+# Scalar variables
+$var1 = "Hello World";   
+$var2 = 14.6;
+
+# Array variables
+ at arr1 = ("zero","one","two","three","four");
+
+# Hash variable, or associative array
+%hash1 = ("one","Monday","two", "Tuesday","three", "Wednesday","four","Thursday");
+
+# Some simple printing
+print $var1; 
+
+# Subroutine
+sub test() {
+	print "ok";
+}
+</textarea>
+
+<textarea id="cp-sql" class="hidden-code">
+--
+-- simple select example
+-- 
+SELECT * FROM books
+	WHERE price > 100.00 and price < 150.00
+	ORDER BY title
+
+SELECT books.title, count(*) AS Authors
+	FROM books
+	JOIN book_authors 
+		ON books.book_number = book_authors.book_number
+	GROUP BY books.title
+
+-- insert, update and delete examples
+	
+INSERT INTO my_table (field1, field2, field3) VALUES ('test', 'N', NULL);
+
+BEGIN WORK;
+	UPDATE inventory SET quantity = quantity - 3 WHERE item = 'pants';
+COMMIT;
+</textarea>
+
+<textarea id="cp-html" class="hidden-code">
+<html>
+<head>
+	<title>CodePress - Online Real Time Syntax Highlighting Editor</title>
+
+	<style type="text/css">
+	@import url(styles.css);	
+	</style>
+	<script type="text/javascript">
+	function getCode() {
+		alert(textWithoutHighlighting);
+	}
+	</script>
+</head>
+<body>
+<div id="logo">
+	<h1><a href="http://codepress.org/">CodePress</a></h1>
+	<h2>Online Real Time Syntax Highlighting Editor</h2>
+	<img src="testimage.gif" />
+</div>
+<div id="languages">
+	<em>choose language:</em> 
+	<button onclick="edit('codepress.php',this)" id="default">PHP</button> 
+	<button onclick="edit('FileManager.java',this)">Java</button> 
+</div>
+</body>
+</html>
+</textarea>
+
+<textarea id="cp-css" class="hidden-code">
+/* CSS comment */
+
+body {
+	color:#000;
+	background-color:white;
+	font:15px Georgia, "Lucida Grande", Arial, sans-serif; 
+	letter-spacing:0.01em;
+	margin:15px;
+}
+
+p { 
+	margin:0 0 15px 0; 
+}
+
+a,a:visited {
+	color:#7f0055;
+}
+
+select {
+	background:#ffffe1;
+}
+
+h1 {
+	color:#7f0055;
+	margin:0;
+	padding:0;
+	font-size:42px;
+}
+</textarea>
+
+
+<script src="codepress.js" type="text/javascript"></script>
+</body>
+</html>

Added: jifty/branches/autoversioning/plugins/CodePress/lib/Jifty/Plugin/CodePress.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/lib/Jifty/Plugin/CodePress.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,77 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::CodePress;
+use base qw/Jifty::Plugin/;
+
+our $VERSION = '0.02';
+
+=head1 NAME
+
+Jifty::Plugin::CodePress
+
+=head1 DESCRIPTION
+
+CodePress, web-based source code editor with syntax highlighting
+
+=head1 SYNOPSIS
+
+In etc/config.yml
+
+  Plugins:
+    - CodePress: {}
+
+In your View do something like:
+
+  $action->form_field( 'source',
+	cols => 80, rows => 25,
+	language => 'perl',
+	render_as => 'Jifty::Plugin::CodePress::Textarea',
+  );
+
+or if you are using L<Template::Declare>
+
+  render_param(
+  	$action => 'source',
+	cols => 80, rows => 25,
+	language => 'perl',
+	render_as => 'Jifty::Plugin::CodePress::Textarea',
+  );
+
+=head1 VERSION
+
+Created from L<https://codepress.svn.sourceforge.net/svnroot/codepress/trunk/stable>
+revision 219 with bunch of local changes to make it play nicer with Jifty.
+
+This involved some hard-coding of paths (because automatic path detection
+from CodePress doesn't work well with Jifty's expectation of JavaScript code
+in C</js/>), addition of C<CodePress.instances> object to track all
+instances and additional JavaScript event handling using C<DOM.Events>
+to remove requirement to call C<CodePress.beforeSubmit> from form submit
+(If you want you can still call it, and it will turn all CodePress editors
+back to textarea).
+
+This also side-stepped problem with original calling schematic which created
+functions with names from element ids. This was problematic with Jifty
+because ids are automatically generated and use dashes (C<->) in them which
+aren't valid JavaScript function names.
+
+=head1 BUGS
+
+There seems to strange interaction between CodePress and Jifty fragments.
+
+=head1 SEE ALSO
+
+L<http://codepress.org/> - project site
+
+=cut
+
+sub init {
+	my $self = shift;
+	Jifty->web->javascript_libs([
+	@{ Jifty->web->javascript_libs },
+	"codepress.js",
+	]);
+}
+
+1;

Added: jifty/branches/autoversioning/plugins/CodePress/lib/Jifty/Plugin/CodePress/Textarea.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/lib/Jifty/Plugin/CodePress/Textarea.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,41 @@
+use warnings;
+use strict;
+
+package Jifty::Plugin::CodePress::Textarea;
+use base qw(Jifty::Web::Form::Field::Textarea);
+
+__PACKAGE__->mk_accessors(qw(language));
+
+=head2 accessors
+
+Provide C<language> accessor, in addition to
+L<Jifty::Web::Form::Field::Textarea>'s default accessors.
+
+=cut
+
+sub accessors { shift->SUPER::accessors(), 'language' }
+
+=head2 render_widget
+
+Renders the textarea widget.
+
+=cut
+
+sub render_widget {
+    my $self  = shift;
+    my $field;
+    $field .= qq!<textarea!;
+    $field .= qq! name="@{[ $self->input_name ]}"!;
+    $field .= qq! id="@{[ $self->element_id ]}"!;
+    $field .= qq! rows="@{[$self->rows || 25]}"!;
+    $field .= qq! cols="@{[$self->cols || 80]}"!;
+    $field .= $self->_widget_class( 'codepress', $self->language );
+    $field .= qq! >!;
+    $field .= Jifty->web->escape($self->current_value) if $self->current_value;
+    $field .= qq!</textarea>\n!;
+
+    Jifty->web->out($field);
+    '';
+}
+
+1;

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/codepress.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/codepress.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,7 @@
+body {margin-top:13px;_margin-top:14px;background:white;font-family:monospace;font-size:13px;margin-left:32px;white-space:pre;background-image:url("images/line-numbers.png");background-repeat:repeat-y;background-position:0 3px;line-height:16px;}
+html>body{background-position:0 2px;}
+P {margin:0;padding:0;border:0;outline:0;display:block;white-space:pre;}
+b, i, s, u, a, em, tt, ins, big, cite, strong, var, dfn {text-decoration:none;font-weight:normal;font-style:normal;font-size:13px;}
+
+body.hide-line-numbers {background:white;margin-left:16px;}
+body.show-line-numbers {background-image:url("images/line-numbers.png");margin-left:32px;}
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/codepress.html
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/codepress.html	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+	<title>CodePress - Real Time Syntax Highlighting Editor written in JavaScript</title>
+	<meta name="description" content="CodePress - source code editor window" />
+
+	<script type="text/javascript">
+	var language = 'generic';
+	var engine = 'older';
+	var ua = navigator.userAgent;
+	var ts = (new Date).getTime(); // timestamp to avoid cache
+	var lh = location.href;
+	
+	if(ua.match('MSIE')) engine = 'msie';
+	else if(ua.match('KHTML')) engine = 'khtml'; 
+	else if(ua.match('Opera')) engine = 'opera'; 
+	else if(ua.match('Gecko')) engine = 'gecko';
+
+	if(lh.match('language=')) language = lh.replace(/.*language=(.*?)(&.*)?$/,'$1');
+
+	document.write('<link type="text/css" href="/static/codepress/codepress.css?ts='+ts+'" rel="stylesheet" />');
+	document.write('<link type="text/css" href="/static/codepress/languages/'+language+'.css?ts='+ts+'" rel="stylesheet" id="cp-lang-style" />');
+	document.write('<scr'+'ipt type="text/javascript" src="/static/codepress/engines/'+engine+'.js?ts='+ts+'"></scr'+'ipt>');
+	document.write('<scr'+'ipt type="text/javascript" src="/static/codepress/languages/'+language+'.js?ts='+ts+'"></scr'+'ipt>');
+	</script>
+
+</head>
+
+<script type="text/javascript">
+if (engine == "gecko") document.write('<body> </body>');
+else if(engine == "msie") document.write('<body><pre></pre></body>');
+else if(engine == "opera") document.write('<body></body>');
+// else if(engine == "khtml") document.write('<body> </body>');
+</script>
+
+</html>

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/gecko.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/gecko.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,273 @@
+/*
+ * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/
+ * 
+ * Copyright (C) 2007 Fernando M.A.d.S. <fermads at gmail.com>
+ *
+ * Developers:
+ *		Fernando M.A.d.S. <fermads at gmail.com>
+ *		Michael Hurni <michael.hurni at gmail.com>
+ * Contributors: 	
+ *		Martin D. Kirk
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the 
+ * GNU Lesser General Public License as published by the Free Software Foundation.
+ * 
+ * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php
+ */
+
+CodePress = {
+	scrolling : false,
+	autocomplete : true,
+
+	// set initial vars and start sh
+	initialize : function() {
+		if(typeof(editor)=='undefined' && !arguments[0]) return;
+		chars = '|32|46|62|'; // charcodes that trigger syntax highlighting
+		cc = '\u2009'; // control char
+		editor = document.getElementsByTagName('body')[0];
+		document.designMode = 'on';
+		document.addEventListener('keypress', this.keyHandler, true);
+		window.addEventListener('scroll', function() { if(!CodePress.scrolling) CodePress.syntaxHighlight('scroll') }, false);
+		completeChars = this.getCompleteChars();
+		completeEndingChars =  this.getCompleteEndingChars();
+	},
+
+	// treat key bindings
+	keyHandler : function(evt) {
+    	keyCode = evt.keyCode;	
+		charCode = evt.charCode;
+		fromChar = String.fromCharCode(charCode);
+
+		if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && charCode!=90)  { // shortcuts = ctrl||appleKey+shift+key!=z(undo) 
+			CodePress.shortcuts(charCode?charCode:keyCode);
+		}
+		else if( (completeEndingChars.indexOf('|'+fromChar+'|')!= -1 || completeChars.indexOf('|'+fromChar+'|')!=-1) && CodePress.autocomplete) { // auto complete
+			if(!CodePress.completeEnding(fromChar))
+			     CodePress.complete(fromChar);
+		}
+	    else if(chars.indexOf('|'+charCode+'|')!=-1||keyCode==13) { // syntax highlighting
+			top.setTimeout(function(){CodePress.syntaxHighlight('generic');},100);
+		}
+		else if(keyCode==9 || evt.tabKey) {  // snippets activation (tab)
+			CodePress.snippets(evt);
+		}
+		else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed
+		 	CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML;
+		}
+		else if((charCode==122||charCode==121||charCode==90) && evt.ctrlKey) { // undo and redo
+			(charCode==121||evt.shiftKey) ? CodePress.actions.redo() :  CodePress.actions.undo(); 
+			evt.preventDefault();
+		}
+		else if(charCode==118 && evt.ctrlKey)  { // handle paste
+		 	top.setTimeout(function(){CodePress.syntaxHighlight('generic');},100);
+		}
+		else if(charCode==99 && evt.ctrlKey)  { // handle cut
+		 	//alert(window.getSelection().getRangeAt(0).toString().replace(/\t/g,'FFF'));
+		}
+
+	},
+
+	// put cursor back to its original position after every parsing
+	findString : function() {
+		if(self.find(cc))
+			window.getSelection().getRangeAt(0).deleteContents();
+	},
+	
+	// split big files, highlighting parts of it
+	split : function(code,flag) {
+		if(flag=='scroll') {
+			this.scrolling = true;
+			return code;
+		}
+		else {
+			this.scrolling = false;
+			mid = code.indexOf(cc);
+			if(mid-2000<0) {ini=0;end=4000;}
+			else if(mid+2000>code.length) {ini=code.length-4000;end=code.length;}
+			else {ini=mid-2000;end=mid+2000;}
+			code = code.substring(ini,end);
+			return code;
+		}
+	},
+	
+	// syntax highlighting parser
+	syntaxHighlight : function(flag) {
+		//if(document.designMode=='off') document.designMode='on'
+		if(flag!='init') window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc));
+
+		o = editor.innerHTML;
+		o = o.replace(/<br>/g,'\n');
+		o = o.replace(/<.*?>/g,'');
+		x = z = this.split(o,flag);
+		x = x.replace(/\n/g,'<br>');
+
+		if(arguments[1]&&arguments[2]) x = x.replace(arguments[1],arguments[2]);
+	
+		for(i=0;i<Language.syntax.length;i++) 
+			x = x.replace(Language.syntax[i].input,Language.syntax[i].output);
+
+		editor.innerHTML = this.actions.history[this.actions.next()] = (flag=='scroll') ? x : o.split(z).join(x); 
+		if(flag!='init') this.findString();
+	},
+	
+	getLastWord : function() {
+		var rangeAndCaret = CodePress.getRangeAndCaret();
+		words = rangeAndCaret[0].substring(rangeAndCaret[1]-40,rangeAndCaret[1]);
+		words = words.replace(/[\s\n\r\);\W]/g,'\n').split('\n');
+		return words[words.length-1].replace(/[\W]/gi,'').toLowerCase();
+	},
+	
+	snippets : function(evt) {
+		var snippets = Language.snippets;	
+		var trigger = this.getLastWord();
+		for (var i=0; i<snippets.length; i++) {
+			if(snippets[i].input == trigger) {
+				var content = snippets[i].output.replace(/</g,'&lt;');
+				content = content.replace(/>/g,'&gt;');
+				if(content.indexOf('$0')<0) content += cc;
+				else content = content.replace(/\$0/,cc);
+				content = content.replace(/\n/g,'<br>');
+				var pattern = new RegExp(trigger+cc,'gi');
+				evt.preventDefault(); // prevent the tab key from being added
+				this.syntaxHighlight('snippets',pattern,content);
+			}
+		}
+	},
+	
+	readOnly : function() {
+		document.designMode = (arguments[0]) ? 'off' : 'on';
+	},
+
+	complete : function(trigger) {
+		window.getSelection().getRangeAt(0).deleteContents();
+		var complete = Language.complete;
+		for (var i=0; i<complete.length; i++) {
+			if(complete[i].input == trigger) {
+				var pattern = new RegExp('\\'+trigger+cc);
+				var content = complete[i].output.replace(/\$0/g,cc);
+				parent.setTimeout(function () { CodePress.syntaxHighlight('complete',pattern,content)},0); // wait for char to appear on screen
+			}
+		}
+	},
+
+	getCompleteChars : function() {
+		var cChars = '';
+		for(var i=0;i<Language.complete.length;i++)
+			cChars += '|'+Language.complete[i].input;
+		return cChars+'|';
+	},
+	
+	getCompleteEndingChars : function() {
+		var cChars = '';
+		for(var i=0;i<Language.complete.length;i++)
+			cChars += '|'+Language.complete[i].output.charAt(Language.complete[i].output.length-1);
+		return cChars+'|';
+	},
+	
+	completeEnding : function(trigger) {
+		var range = window.getSelection().getRangeAt(0);
+		try {
+			range.setEnd(range.endContainer, range.endOffset+1)
+		}
+		catch(e) {
+			return false;
+		}
+		var next_character = range.toString()
+		range.setEnd(range.endContainer, range.endOffset-1)
+		if(next_character != trigger) return false;
+		else {
+			range.setEnd(range.endContainer, range.endOffset+1)
+			range.deleteContents();
+			return true;
+		}
+	},
+	
+	shortcuts : function() {
+		var cCode = arguments[0];
+		if(cCode==13) cCode = '[enter]';
+		else if(cCode==32) cCode = '[space]';
+		else cCode = '['+String.fromCharCode(charCode).toLowerCase()+']';
+		for(var i=0;i<Language.shortcuts.length;i++)
+			if(Language.shortcuts[i].input == cCode)
+				this.insertCode(Language.shortcuts[i].output,false);
+	},
+	
+	getRangeAndCaret : function() {	
+		var range = window.getSelection().getRangeAt(0);
+		var range2 = range.cloneRange();
+		var node = range.endContainer;			
+		var caret = range.endOffset;
+		range2.selectNode(node);	
+		return [range2.toString(),caret];
+	},
+	
+	insertCode : function(code,replaceCursorBefore) {
+		var range = window.getSelection().getRangeAt(0);
+		var node = window.document.createTextNode(code);
+		var selct = window.getSelection();
+		var range2 = range.cloneRange();
+		// Insert text at cursor position
+		selct.removeAllRanges();
+		range.deleteContents();
+		range.insertNode(node);
+		// Move the cursor to the end of text
+		range2.selectNode(node);		
+		range2.collapse(replaceCursorBefore);
+		selct.removeAllRanges();
+		selct.addRange(range2);
+	},
+	
+	// get code from editor
+	getCode : function() {
+		var code = editor.innerHTML;
+		code = code.replace(/<br>/g,'\n');
+		code = code.replace(/\u2009/g,'');
+		code = code.replace(/<.*?>/g,'');
+		code = code.replace(/&lt;/g,'<');
+		code = code.replace(/&gt;/g,'>');
+		code = code.replace(/&amp;/gi,'&');
+		return code;
+	},
+
+	// put code inside editor
+	setCode : function() {
+		var code = arguments[0];
+		code = code.replace(/\u2009/gi,'');
+		code = code.replace(/&/gi,'&amp;');
+       	code = code.replace(/</g,'&lt;');
+        code = code.replace(/>/g,'&gt;');
+		editor.innerHTML = code;
+	},
+
+	// undo and redo methods
+	actions : {
+		pos : -1, // actual history position
+		history : [], // history vector
+		
+		undo : function() {
+			if(editor.innerHTML.indexOf(cc)==-1){
+				window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc));
+			 	this.history[this.pos] = editor.innerHTML;
+			}
+			this.pos--;
+			if(typeof(this.history[this.pos])=='undefined') this.pos++;
+			editor.innerHTML = this.history[this.pos];
+			CodePress.findString();
+		},
+		
+		redo : function() {
+			this.pos++;
+			if(typeof(this.history[this.pos])=='undefined') this.pos--;
+			editor.innerHTML = this.history[this.pos];
+			CodePress.findString();
+		},
+		
+		next : function() { // get next vector position and clean old ones
+			if(this.pos>20) this.history[this.pos-21] = undefined;
+			return ++this.pos;
+		}
+	}
+}
+
+Language={};
+window.addEventListener('load', function() { CodePress.initialize('new'); }, true);
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/khtml.js
==============================================================================

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/msie.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/msie.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,304 @@
+/*
+ * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/
+ * 
+ * Copyright (C) 2007 Fernando M.A.d.S. <fermads at gmail.com>
+ *
+ * Developers:
+ *		Fernando M.A.d.S. <fermads at gmail.com>
+ *		Michael Hurni <michael.hurni at gmail.com>
+ * Contributors: 	
+ *		Martin D. Kirk
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the 
+ * GNU Lesser General Public License as published by the Free Software Foundation.
+ * 
+ * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php
+ */
+
+CodePress = {
+	scrolling : false,
+	autocomplete : true,
+	
+	// set initial vars and start sh
+	initialize : function() {
+		if(typeof(editor)=='undefined' && !arguments[0]) return;
+		chars = '|32|46|62|'; // charcodes that trigger syntax highlighting
+		cc = '\u2009'; // control char
+		editor = document.getElementsByTagName('pre')[0];
+		editor.contentEditable = 'true';
+		document.getElementsByTagName('body')[0].onfocus = function() {editor.focus();}
+		document.attachEvent('onkeydown', this.metaHandler);
+		document.attachEvent('onkeypress', this.keyHandler);
+		window.attachEvent('onscroll', function() { if(!CodePress.scrolling) setTimeout(function(){CodePress.syntaxHighlight('scroll')},1)});
+		completeChars = this.getCompleteChars();
+		completeEndingChars =  this.getCompleteEndingChars();
+		setTimeout(function() { window.scroll(0,0) },50); // scroll IE to top
+	},
+	
+	// treat key bindings
+	keyHandler : function(evt) {
+		charCode = evt.keyCode;
+		fromChar = String.fromCharCode(charCode);
+		
+		if( (completeEndingChars.indexOf('|'+fromChar+'|')!= -1 || completeChars.indexOf('|'+fromChar+'|')!=-1  )&& CodePress.autocomplete) { // auto complete
+			if(!CodePress.completeEnding(fromChar))
+			     CodePress.complete(fromChar);
+		}
+	    else if(chars.indexOf('|'+charCode+'|')!=-1||charCode==13) { // syntax highlighting
+		 	CodePress.syntaxHighlight('generic');
+		}
+	},
+
+	metaHandler : function(evt) {
+		keyCode = evt.keyCode;
+		
+		if(keyCode==9 || evt.tabKey) { 
+			CodePress.snippets();
+		}
+		else if((keyCode==122||keyCode==121||keyCode==90) && evt.ctrlKey) { // undo and redo
+			(keyCode==121||evt.shiftKey) ? CodePress.actions.redo() :  CodePress.actions.undo(); 
+			evt.returnValue = false;
+		}
+		else if(keyCode==34||keyCode==33) { // handle page up/down for IE
+			self.scrollBy(0, (keyCode==34) ? 200 : -200); 
+			evt.returnValue = false;
+		}
+		else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed
+		 	CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML;
+		}
+		else if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && keyCode!=90)  { // shortcuts = ctrl||appleKey+shift+key!=z(undo) 
+			CodePress.shortcuts(keyCode);
+			evt.returnValue = false;
+		}
+		else if(keyCode==86 && evt.ctrlKey)  { // handle paste
+			window.clipboardData.setData('Text',window.clipboardData.getData('Text').replace(/\t/g,'\u2008'));
+		 	top.setTimeout(function(){CodePress.syntaxHighlight('paste');},10);
+		}
+		else if(keyCode==67 && evt.ctrlKey)  { // handle cut
+			// window.clipboardData.setData('Text',x[0]);
+			// code = window.clipboardData.getData('Text');
+		}
+	},
+
+	// put cursor back to its original position after every parsing
+	
+	
+	findString : function() {
+		range = self.document.body.createTextRange();
+		if(range.findText(cc)){
+			range.select();
+			range.text = '';
+		}
+	},
+	
+	// split big files, highlighting parts of it
+	split : function(code,flag) {
+		if(flag=='scroll') {
+			this.scrolling = true;
+			return code;
+		}
+		else {
+			this.scrolling = false;
+			mid = code.indexOf(cc);
+			if(mid-2000<0) {ini=0;end=4000;}
+			else if(mid+2000>code.length) {ini=code.length-4000;end=code.length;}
+			else {ini=mid-2000;end=mid+2000;}
+			code = code.substring(ini,end);
+			return code.substring(code.indexOf('<P>'),code.lastIndexOf('</P>')+4);
+		}
+	},
+	
+	// syntax highlighting parser
+	syntaxHighlight : function(flag) {
+		if(flag!='init') document.selection.createRange().text = cc;
+		o = editor.innerHTML;
+		if(flag=='paste') { // fix pasted text
+			o = o.replace(/<BR>/g,'\r\n'); 
+			o = o.replace(/\u2008/g,'\t');
+		}
+		o = o.replace(/<P>/g,'\n');
+		o = o.replace(/<\/P>/g,'\r');
+		o = o.replace(/<.*?>/g,'');
+		o = o.replace(/&nbsp;/g,'');			
+		o = '<PRE><P>'+o+'</P></PRE>';
+		o = o.replace(/\n\r/g,'<P></P>');
+		o = o.replace(/\n/g,'<P>');
+		o = o.replace(/\r/g,'<\/P>');
+		o = o.replace(/<P>(<P>)+/,'<P>');
+		o = o.replace(/<\/P>(<\/P>)+/,'</P>');
+		o = o.replace(/<P><\/P>/g,'<P><BR/></P>');
+		x = z = this.split(o,flag);
+
+		if(arguments[1]&&arguments[2]) x = x.replace(arguments[1],arguments[2]);
+	
+		for(i=0;i<Language.syntax.length;i++) 
+			x = x.replace(Language.syntax[i].input,Language.syntax[i].output);
+			
+		editor.innerHTML = this.actions.history[this.actions.next()] = (flag=='scroll') ? x : o.replace(z,x);
+		if(flag!='init') this.findString();
+	},
+
+	snippets : function(evt) {
+		var snippets = Language.snippets;
+		var trigger = this.getLastWord();
+		for (var i=0; i<snippets.length; i++) {
+			if(snippets[i].input == trigger) {
+				var content = snippets[i].output.replace(/</g,'&lt;');
+				content = content.replace(/>/g,'&gt;');
+				if(content.indexOf('$0')<0) content += cc;
+				else content = content.replace(/\$0/,cc);
+				content = content.replace(/\n/g,'</P><P>');
+				var pattern = new RegExp(trigger+cc,"gi");
+				this.syntaxHighlight('snippets',pattern,content);
+			}
+		}
+	},
+	
+	readOnly : function() {
+		editor.contentEditable = (arguments[0]) ? 'false' : 'true';
+	},
+	
+	complete : function(trigger) {
+		var complete = Language.complete;
+		for (var i=0; i<complete.length; i++) {
+			if(complete[i].input == trigger) {
+				var pattern = new RegExp('\\'+trigger+cc);
+				var content = complete[i].output.replace(/\$0/g,cc);
+				setTimeout(function () { CodePress.syntaxHighlight('complete',pattern,content)},0); // wait for char to appear on screen
+			}
+		}
+	},
+	
+	getCompleteChars : function() {
+		var cChars = '';
+		for(var i=0;i<Language.complete.length;i++)
+			cChars += '|'+Language.complete[i].input;
+		return cChars+'|';
+	},
+
+	getCompleteEndingChars : function() {
+		var cChars = '';
+		for(var i=0;i<Language.complete.length;i++)
+			cChars += '|'+Language.complete[i].output.charAt(Language.complete[i].output.length-1);
+		return cChars+'|';
+	},
+
+	completeEnding : function(trigger) {
+		var range = document.selection.createRange();
+		try {
+			range.moveEnd('character', 1)
+		}
+		catch(e) {
+			return false;
+		}
+		var next_character = range.text
+		range.moveEnd('character', -1)
+		if(next_character != trigger )  return false;
+		else {
+			range.moveEnd('character', 1)
+			range.text=''
+			return true;
+		}
+	},	
+
+	shortcuts : function() {
+		var cCode = arguments[0];
+		if(cCode==13) cCode = '[enter]';
+		else if(cCode==32) cCode = '[space]';
+		else cCode = '['+String.fromCharCode(keyCode).toLowerCase()+']';
+		for(var i=0;i<Language.shortcuts.length;i++)
+			if(Language.shortcuts[i].input == cCode)
+				this.insertCode(Language.shortcuts[i].output,false);
+	},
+	
+	getLastWord : function() {
+		var rangeAndCaret = CodePress.getRangeAndCaret();
+		words = rangeAndCaret[0].substring(rangeAndCaret[1]-40,rangeAndCaret[1]);
+		words = words.replace(/[\s\n\r\);\W]/g,'\n').split('\n');
+		return words[words.length-1].replace(/[\W]/gi,'').toLowerCase();
+	}, 
+
+	getRangeAndCaret : function() {	
+		var range = document.selection.createRange();
+		var caret = Math.abs(range.moveStart('character', -1000000)+1);
+		range = this.getCode();
+		range = range.replace(/\n\r/gi,'  ');
+		range = range.replace(/\n/gi,'');
+		return [range.toString(),caret];
+	},
+	
+	insertCode : function(code,replaceCursorBefore) {
+		var repdeb = '';
+		var repfin = '';
+		
+		if(replaceCursorBefore) { repfin = code; }
+		else { repdeb = code; }
+		
+		if(typeof document.selection != 'undefined') {
+			var range = document.selection.createRange();
+			range.text = repdeb + repfin;
+			range = document.selection.createRange();
+			range.move('character', -repfin.length);
+			range.select();	
+		}	
+	},
+
+	// get code from editor	
+	getCode : function() {
+		var code = editor.innerHTML;
+		code = code.replace(/<br>/g,'\n');
+		code = code.replace(/<\/p>/gi,'\r');
+		code = code.replace(/<p>/i,''); // IE first line fix
+		code = code.replace(/<p>/gi,'\n');
+		code = code.replace(/&nbsp;/gi,'');
+		code = code.replace(/\u2009/g,'');
+		code = code.replace(/<.*?>/g,'');
+		code = code.replace(/&lt;/g,'<');
+		code = code.replace(/&gt;/g,'>');
+		code = code.replace(/&amp;/gi,'&');
+		return code;
+	},
+
+	// put code inside editor
+	setCode : function() {
+		var code = arguments[0];
+		code = code.replace(/\u2009/gi,'');
+		code = code.replace(/&/gi,'&amp;');		
+       	code = code.replace(/</g,'&lt;');
+        code = code.replace(/>/g,'&gt;');
+		editor.innerHTML = '<pre>'+code+'</pre>';
+	},
+
+	
+	// undo and redo methods
+	actions : {
+		pos : -1, // actual history position
+		history : [], // history vector
+		
+		undo : function() {
+			if(editor.innerHTML.indexOf(cc)==-1){
+				document.selection.createRange().text = cc;
+			 	this.history[this.pos] = editor.innerHTML;
+			}
+			this.pos--;
+			if(typeof(this.history[this.pos])=='undefined') this.pos++;
+			editor.innerHTML = this.history[this.pos];
+			CodePress.findString();
+		},
+		
+		redo : function() {
+			this.pos++;
+			if(typeof(this.history[this.pos])=='undefined') this.pos--;
+			editor.innerHTML = this.history[this.pos];
+			CodePress.findString();
+		},
+		
+		next : function() { // get next vector position and clean old ones
+			if(this.pos>20) this.history[this.pos-21] = undefined;
+			return ++this.pos;
+		}
+	}
+}
+
+Language={};
+window.attachEvent('onload', function() { CodePress.initialize('new');});
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/older.js
==============================================================================

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/opera.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/engines/opera.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,260 @@
+/*
+ * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/
+ * 
+ * Copyright (C) 2007 Fernando M.A.d.S. <fermads at gmail.com>
+ *
+ * Contributors :
+ *
+ * 	Michael Hurni <michael.hurni at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the 
+ * GNU Lesser General Public License as published by the Free Software Foundation.
+ * 
+ * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php
+ */
+
+
+CodePress = {
+	scrolling : false,
+	autocomplete : true,
+
+	// set initial vars and start sh
+	initialize : function() {
+		if(typeof(editor)=='undefined' && !arguments[0]) return;
+		chars = '|32|46|62|'; // charcodes that trigger syntax highlighting
+		cc = '\u2009'; // control char
+		editor = document.getElementsByTagName('body')[0];
+		document.designMode = 'on';
+		document.addEventListener('keyup', this.keyHandler, true);
+		window.addEventListener('scroll', function() { if(!CodePress.scrolling) CodePress.syntaxHighlight('scroll') }, false);
+		completeChars = this.getCompleteChars();
+//		CodePress.syntaxHighlight('init');
+	},
+
+	// treat key bindings
+	keyHandler : function(evt) {
+    	keyCode = evt.keyCode;	
+		charCode = evt.charCode;
+
+		if((evt.ctrlKey || evt.metaKey) && evt.shiftKey && charCode!=90)  { // shortcuts = ctrl||appleKey+shift+key!=z(undo) 
+			CodePress.shortcuts(charCode?charCode:keyCode);
+		}
+		else if(completeChars.indexOf('|'+String.fromCharCode(charCode)+'|')!=-1 && CodePress.autocomplete) { // auto complete
+			CodePress.complete(String.fromCharCode(charCode));
+		}
+	    else if(chars.indexOf('|'+charCode+'|')!=-1||keyCode==13) { // syntax highlighting
+		 	CodePress.syntaxHighlight('generic');
+		}
+		else if(keyCode==9 || evt.tabKey) {  // snippets activation (tab)
+			CodePress.snippets(evt);
+		}
+		else if(keyCode==46||keyCode==8) { // save to history when delete or backspace pressed
+		 	CodePress.actions.history[CodePress.actions.next()] = editor.innerHTML;
+		}
+		else if((charCode==122||charCode==121||charCode==90) && evt.ctrlKey) { // undo and redo
+			(charCode==121||evt.shiftKey) ? CodePress.actions.redo() :  CodePress.actions.undo(); 
+			evt.preventDefault();
+		}
+		else if(keyCode==86 && evt.ctrlKey)  { // paste
+			// TODO: pasted text should be parsed and highlighted
+		}
+	},
+
+	// put cursor back to its original position after every parsing
+	findString : function() {
+		var sel = window.getSelection();
+		var range = window.document.createRange();
+		var span = window.document.getElementsByTagName('span')[0];
+			
+		range.selectNode(span);
+		sel.removeAllRanges();
+		sel.addRange(range);
+		span.parentNode.removeChild(span);
+		//if(self.find(cc))
+		//window.getSelection().getRangeAt(0).deleteContents();
+	},
+	
+	// split big files, highlighting parts of it
+	split : function(code,flag) {
+		if(flag=='scroll') {
+			this.scrolling = true;
+			return code;
+		}
+		else {
+			this.scrolling = false;
+			mid = code.indexOf('<SPAN>');
+			if(mid-2000<0) {ini=0;end=4000;}
+			else if(mid+2000>code.length) {ini=code.length-4000;end=code.length;}
+			else {ini=mid-2000;end=mid+2000;}
+			code = code.substring(ini,end);
+			return code;
+		}
+	},
+	
+	// syntax highlighting parser
+	syntaxHighlight : function(flag) {
+		//if(document.designMode=='off') document.designMode='on'
+		if(flag!='init') {
+			var span = document.createElement('span');
+			window.getSelection().getRangeAt(0).insertNode(span);
+		}
+
+		o = editor.innerHTML;
+//		o = o.replace(/<br>/g,'\r\n');
+//		o = o.replace(/<(b|i|s|u|a|em|tt|ins|big|cite|strong)?>/g,'');
+		//alert(o)
+		o = o.replace(/<(?!span|\/span|br).*?>/gi,'');
+//		alert(o)
+//		x = o;
+		x = z = this.split(o,flag);
+		//alert(z)
+//		x = x.replace(/\r\n/g,'<br>');
+		x = x.replace(/\t/g, '        ');
+
+
+		if(arguments[1]&&arguments[2]) x = x.replace(arguments[1],arguments[2]);
+	
+		for(i=0;i<Language.syntax.length;i++) 
+			x = x.replace(Language.syntax[i].input,Language.syntax[i].output);
+
+		editor.innerHTML = this.actions.history[this.actions.next()] = (flag=='scroll') ? x : o.split(z).join(x); 
+
+		if(flag!='init') this.findString();
+	},
+	
+	getLastWord : function() {
+		var rangeAndCaret = CodePress.getRangeAndCaret();
+		words = rangeAndCaret[0].substring(rangeAndCaret[1]-40,rangeAndCaret[1]);
+		words = words.replace(/[\s\n\r\);\W]/g,'\n').split('\n');
+		return words[words.length-1].replace(/[\W]/gi,'').toLowerCase();
+	}, 
+	
+	snippets : function(evt) {
+		var snippets = Language.snippets;	
+		var trigger = this.getLastWord();
+		for (var i=0; i<snippets.length; i++) {
+			if(snippets[i].input == trigger) {
+				var content = snippets[i].output.replace(/</g,'&lt;');
+				content = content.replace(/>/g,'&gt;');
+				if(content.indexOf('$0')<0) content += cc;
+				else content = content.replace(/\$0/,cc);
+				content = content.replace(/\n/g,'<br>');
+				var pattern = new RegExp(trigger+cc,'gi');
+				evt.preventDefault(); // prevent the tab key from being added
+				this.syntaxHighlight('snippets',pattern,content);
+			}
+		}
+	},
+	
+	readOnly : function() {
+		document.designMode = (arguments[0]) ? 'off' : 'on';
+	},
+
+	complete : function(trigger) {
+		window.getSelection().getRangeAt(0).deleteContents();
+		var complete = Language.complete;
+		for (var i=0; i<complete.length; i++) {
+			if(complete[i].input == trigger) {
+				var pattern = new RegExp('\\'+trigger+cc);
+				var content = complete[i].output.replace(/\$0/g,cc);
+				parent.setTimeout(function () { CodePress.syntaxHighlight('complete',pattern,content)},0); // wait for char to appear on screen
+			}
+		}
+	},
+
+	getCompleteChars : function() {
+		var cChars = '';
+		for(var i=0;i<Language.complete.length;i++)
+			cChars += '|'+Language.complete[i].input;
+		return cChars+'|';
+	},
+
+	shortcuts : function() {
+		var cCode = arguments[0];
+		if(cCode==13) cCode = '[enter]';
+		else if(cCode==32) cCode = '[space]';
+		else cCode = '['+String.fromCharCode(charCode).toLowerCase()+']';
+		for(var i=0;i<Language.shortcuts.length;i++)
+			if(Language.shortcuts[i].input == cCode)
+				this.insertCode(Language.shortcuts[i].output,false);
+	},
+	
+	getRangeAndCaret : function() {	
+		var range = window.getSelection().getRangeAt(0);
+		var range2 = range.cloneRange();
+		var node = range.endContainer;			
+		var caret = range.endOffset;
+		range2.selectNode(node);	
+		return [range2.toString(),caret];
+	},
+	
+	insertCode : function(code,replaceCursorBefore) {
+		var range = window.getSelection().getRangeAt(0);
+		var node = window.document.createTextNode(code);
+		var selct = window.getSelection();
+		var range2 = range.cloneRange();
+		// Insert text at cursor position
+		selct.removeAllRanges();
+		range.deleteContents();
+		range.insertNode(node);
+		// Move the cursor to the end of text
+		range2.selectNode(node);		
+		range2.collapse(replaceCursorBefore);
+		selct.removeAllRanges();
+		selct.addRange(range2);
+	},
+	
+	// get code from editor
+	getCode : function() {
+		var code = editor.innerHTML;
+		code = code.replace(/<br>/g,'\n');
+		code = code.replace(/\u2009/g,'');
+		code = code.replace(/<.*?>/g,'');
+		code = code.replace(/&lt;/g,'<');
+		code = code.replace(/&gt;/g,'>');
+		code = code.replace(/&amp;/gi,'&');
+		return code;
+	},
+
+	// put code inside editor
+	setCode : function() {
+		var code = arguments[0];
+		code = code.replace(/\u2009/gi,'');
+		code = code.replace(/&/gi,'&amp;');
+       	code = code.replace(/</g,'&lt;');
+        code = code.replace(/>/g,'&gt;');
+		editor.innerHTML = code;
+	},
+
+	// undo and redo methods
+	actions : {
+		pos : -1, // actual history position
+		history : [], // history vector
+		
+		undo : function() {
+			if(editor.innerHTML.indexOf(cc)==-1){
+				window.getSelection().getRangeAt(0).insertNode(document.createTextNode(cc));
+			 	this.history[this.pos] = editor.innerHTML;
+			}
+			this.pos--;
+			if(typeof(this.history[this.pos])=='undefined') this.pos++;
+			editor.innerHTML = this.history[this.pos];
+			CodePress.findString();
+		},
+		
+		redo : function() {
+			this.pos++;
+			if(typeof(this.history[this.pos])=='undefined') this.pos--;
+			editor.innerHTML = this.history[this.pos];
+			CodePress.findString();
+		},
+		
+		next : function() { // get next vector position and clean old ones
+			if(this.pos>20) this.history[this.pos-21] = undefined;
+			return ++this.pos;
+		}
+	}
+}
+
+Language={};
+window.addEventListener('load', function() { CodePress.initialize('new'); }, true);

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/images/line-numbers.png
==============================================================================
Binary file. No diff available.

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/asp.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/asp.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,71 @@
+/*
+ * CodePress color styles for ASP-VB syntax highlighting
+ * By Martin D. Kirk
+ */
+/* tags */
+
+b {
+	color:#000080;
+} 
+/* comments */
+big, big b, big em, big ins, big s, strong i, strong i b, strong i s, strong i u, strong i a, strong i a u, strong i s u {
+	color:gray;
+	font-weight:normal;
+}
+/* ASP comments */
+strong dfn, strong dfn a,strong dfn var, strong dfn a u, strong dfn u{
+	color:gray;
+	font-weight:normal;
+}
+ /* attributes */ 
+s, s b, span s u, span s cite, strong span s {
+	color:#5656fa ;
+	font-weight:normal;
+}
+ /* strings */ 
+strong s,strong s b, strong s u, strong s cite {
+	color:#009900;
+	font-weight:normal;
+}
+strong ins{
+	color:#000000;
+	font-weight:bold;
+}
+ /* Syntax */
+strong a, strong a u {
+	color:#0000FF;
+	font-weight:;
+}
+ /* Native Keywords */
+strong u {
+	color:#990099;
+	font-weight:bold;
+}
+/* Numbers */
+strong var{
+	color:#FF0000;
+}
+/* ASP Language */
+span{
+	color:#990000;
+	font-weight:bold;
+}
+strong i,strong a i, strong u i {
+	color:#009999;
+}
+/* style */
+em {
+	color:#800080;
+	font-style:normal;
+}
+ /* script */ 
+ins {
+	color:#800000;
+	font-weight:bold;
+}
+
+/* <?php and ?> */
+cite, s cite {
+	color:red;
+	font-weight:bold;
+}
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/asp.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/asp.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,117 @@
+/*
+ * CodePress regular expressions for ASP-vbscript syntax highlighting
+ */
+
+// ASP VBScript
+Language.syntax = [
+// all tags
+	{ input : /(&lt;[^!%|!%@]*?&gt;)/g, output : '<b>$1</b>' }, 
+// style tags	
+	{ input : /(&lt;style.*?&gt;)(.*?)(&lt;\/style&gt;)/g, output : '<em>$1</em><em>$2</em><em>$3</em>' }, 
+// script tags	
+	{ input : /(&lt;script.*?&gt;)(.*?)(&lt;\/script&gt;)/g, output : '<ins>$1</ins><ins>$2</ins><ins>$3</ins>' }, 
+// strings "" and attributes
+	{ input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, 
+// ASP Comment
+	{ input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<dfn>\'$1$2</dfn>'}, 
+// <%.*
+	{ input : /(&lt;%)/g, output : '<strong>$1' }, 
+// .*%>	
+	{ input : /(%&gt;)/g, output : '$1</strong>' }, 
+// <%@...%>	
+	{ input : /(&lt;%@)(.+?)(%&gt;)/gi, output : '$1<span>$2</span>$3' }, 
+//Numbers	
+	{ input : /\b([\d]+)\b/g, output : '<var>$1</var>' }, 
+// Reserved Words 1 (Blue)
+	{ input : /\b(And|As|ByRef|ByVal|Call|Case|Class|Const|Dim|Do|Each|Else|ElseIf|Empty|End|Eqv|Exit|False|For|Function)\b/gi, output : '<a>$1</a>' }, 
+	{ input : /\b(Get|GoTo|If|Imp|In|Is|Let|Loop|Me|Mod|Enum|New|Next|Not|Nothing|Null|On|Option|Or|Private|Public|ReDim|Rem)\b/gi, output : '<a>$1</a>' }, 
+	{ input : /\b(Resume|Select|Set|Stop|Sub|Then|To|True|Until|Wend|While|With|Xor|Execute|Randomize|Erase|ExecuteGlobal|Explicit|step)\b/gi, output : '<a>$1</a>' }, 
+// Reserved Words 2 (Purple)	
+	{ input : /\b(Abandon|Abs|AbsolutePage|AbsolutePosition|ActiveCommand|ActiveConnection|ActualSize|AddHeader|AddNew|AppendChunk)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(AppendToLog|Application|Array|Asc|Atn|Attributes|BeginTrans|BinaryRead|BinaryWrite|BOF|Bookmark|Boolean|Buffer|Byte)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(CacheControl|CacheSize|Cancel|CancelBatch|CancelUpdate|CBool|CByte|CCur|CDate|CDbl|Charset|Chr|CInt|Clear)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(ClientCertificate|CLng|Clone|Close|CodePage|CommandText|CommandType|CommandTimeout|CommitTrans|CompareBookmarks|ConnectionString|ConnectionTimeout)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Contents|ContentType|Cookies|Cos|CreateObject|CreateParameter|CSng|CStr|CursorLocation|CursorType|DataMember|DataSource|Date|DateAdd|DateDiff)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(DatePart|DateSerial|DateValue|Day|DefaultDatabase|DefinedSize|Delete|Description|Double|EditMode|Eof|EOF|err|Error)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Exp|Expires|ExpiresAbsolute|Filter|Find|Fix|Flush|Form|FormatCurrency|FormatDateTime|FormatNumber|FormatPercent)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(GetChunk|GetLastError|GetRows|GetString|Global|HelpContext|HelpFile|Hex|Hour|HTMLEncode|IgnoreCase|Index|InStr|InStrRev)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Int|Integer|IsArray|IsClientConnected|IsDate|IsolationLevel|Join|LBound|LCase|LCID|Left|Len|Lock|LockType|Log|Long|LTrim)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(MapPath|MarshalOptions|MaxRecords|Mid|Minute|Mode|Month|MonthName|Move|MoveFirst|MoveLast|MoveNext|MovePrevious|Name|NextRecordset)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Now|Number|NumericScale|ObjectContext|Oct|Open|OpenSchema|OriginalValue|PageCount|PageSize|Pattern|PICS|Precision|Prepared|Property)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Provider|QueryString|RecordCount|Redirect|RegExp|Remove|RemoveAll|Replace|Requery|Request|Response|Resync|Right|Rnd)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(RollbackTrans|RTrim|Save|ScriptTimeout|Second|Seek|Server|ServerVariables|Session|SessionID|SetAbort|SetComplete|Sgn)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Sin|Size|Sort|Source|Space|Split|Sqr|State|StaticObjects|Status|StayInSync|StrComp|String|StrReverse|Supports|Tan|Time)\b/gi, output : '<u>$1</u>' },
+	{ input : /\b(Timeout|Timer|TimeSerial|TimeValue|TotalBytes|Transfer|Trim|Type|Type|UBound|UCase|UnderlyingValue|UnLock|Update|UpdateBatch)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(URLEncode|Value|Value|Version|Weekday|WeekdayName|Write|Year)\b/gi, output : '<u>$1</u>' }, 
+// Reserved Words 3 (Turquis)
+	{ input : /\b(vbBlack|vbRed|vbGreen|vbYellow|vbBlue|vbMagenta|vbCyan|vbWhite|vbBinaryCompare|vbTextCompare)\b/gi, output : '<i>$1</i>' }, 
+  	{ input : /\b(vbSunday|vbMonday|vbTuesday|vbWednesday|vbThursday|vbFriday|vbSaturday|vbUseSystemDayOfWeek)\b/gi, output : '<i>$1</i>' }, 
+	{ input : /\b(vbFirstJan1|vbFirstFourDays|vbFirstFullWeek|vbGeneralDate|vbLongDate|vbShortDate|vbLongTime|vbShortTime)\b/gi, output : '<i>$1</i>' }, 
+	{ input : /\b(vbObjectError|vbCr|VbCrLf|vbFormFeed|vbLf|vbNewLine|vbNullChar|vbNullString|vbTab|vbVerticalTab|vbUseDefault|vbTrue)\b/gi, output : '<i>$1</i>' }, 
+	{ input : /\b(vbFalse|vbEmpty|vbNull|vbInteger|vbLong|vbSingle|vbDouble|vbCurrency|vbDate|vbString|vbObject|vbError|vbBoolean|vbVariant)\b/gi, output : '<i>$1</i>' }, 
+	{ input : /\b(vbDataObject|vbDecimal|vbByte|vbArray)\b/gi, output : '<i>$1</i>' },
+// html comments
+	{ input : /(&lt;!--.*?--&gt.)/g, output : '<big>$1</big>' } 
+]
+
+Language.Functions = [ 
+  	// Output at index 0, must be the desired tagname surrounding a $1
+	// Name is the index from the regex that marks the functionname
+	{input : /(function|sub)([ ]*?)(\w+)([ ]*?\()/gi , output : '<ins>$1</ins>', name : '$3'}
+]
+
+Language.snippets = [
+//Conditional
+	{ input : 'if', output : 'If $0 Then\n\t\nEnd If' },
+	{ input : 'ifelse', output : 'If $0 Then\n\t\n\nElse\n\t\nEnd If' },
+	{ input : 'case', output : 'Select Case $0\n\tCase ?\n\tCase Else\nEnd Select'},
+//Response
+	{ input : 'rw', output : 'Response.Write( $0 )' },
+	{ input : 'resc', output : 'Response.Cookies( $0 )' },
+	{ input : 'resb', output : 'Response.Buffer'},
+	{ input : 'resflu', output : 'Response.Flush()'},
+	{ input : 'resend', output : 'Response.End'},
+//Request
+	{ input : 'reqc', output : 'Request.Cookies( $0 )' },
+	{ input : 'rq', output : 'Request.Querystring("$0")' },
+	{ input : 'rf', output : 'Request.Form("$0")' },
+//FSO
+	{ input : 'fso', output : 'Set fso = Server.CreateObject("Scripting.FileSystemObject")\n$0' },
+	{ input : 'setfo', output : 'Set fo = fso.getFolder($0)' },
+	{ input : 'setfi', output : 'Set fi = fso.getFile($0)' },
+	{ input : 'twr', output : 'Set f = fso.CreateTextFile($0,true)\'overwrite\nf.WriteLine()\nf.Close'},
+	{ input : 'tre', output : 'Set f = fso.OpenTextFile($0, 1)\nf.ReadAll\nf.Close'},
+//Server
+	{ input : 'mapp', output : 'Server.Mappath($0)' },
+//Loops
+	{ input : 'foreach', output : 'For Each $0 in ?\n\t\nNext' },
+	{ input : 'for', output : 'For $0 to ? step ?\n\t\nNext' },
+	{ input : 'do', output : 'Do While($0)\n\t\nLoop' },
+	{ input : 'untilrs', output : 'do until rs.eof\n\t\nrs.movenext\nloop' },
+//ADO
+	{ input : 'adorec', output : 'Set rs = Server.CreateObject("ADODB.Recordset")' },
+	{ input : 'adocon', output : 'Set Conn = Server.CreateObject("ADODB.Connection")' },
+	{ input : 'adostr', output : 'Set oStr = Server.CreateObject("ADODB.Stream")' },
+//Http Request
+	{ input : 'xmlhttp', output : 'Set xmlHttp = Server.CreateObject("Microsoft.XMLHTTP")\nxmlHttp.open("GET", $0, false)\nxmlHttp.send()\n?=xmlHttp.responseText' },
+	{ input : 'xmldoc', output : 'Set xmldoc = Server.CreateObject("Microsoft.XMLDOM")\nxmldoc.async=false\nxmldoc.load(request)'},
+//Functions
+	{ input : 'func', output : 'Function $0()\n\t\n\nEnd Function'},
+	{ input : 'sub', output : 'Sub $0()\n\t\nEnd Sub'}
+
+]
+
+Language.complete = [
+	//{ input : '\'', output : '\'$0\'' },
+	{ input : '"', output : '"$0"' },
+	{ input : '(', output : '\($0\)' },
+	{ input : '[', output : '\[$0\]' },
+	{ input : '{', output : '{\n\t$0\n}' }		
+]
+
+Language.shortcuts = [
+	{ input : '[space]', output : '&nbsp;' },
+	{ input : '[enter]', output : '<br />' } ,
+	{ input : '[j]', output : 'testing' },
+	{ input : '[7]', output : '&amp;' }
+]
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/csharp.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/csharp.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,9 @@
+/*
+ * CodePress color styles for Java syntax highlighting
+ * By Edwin de Jonge
+ */
+
+b {color:#7F0055;font-weight:bold;font-style:normal;} /* reserved words */
+a {color:#2A0088;font-weight:bold;font-style:normal;} /* types */
+i, i b, i s {color:#3F7F5F;font-weight:bold;} /* comments */
+s, s b {color:#2A00FF;font-weight:normal;} /* strings */
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/csharp.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/csharp.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,25 @@
+/*
+ * CodePress regular expressions for C# syntax highlighting
+ * By Edwin de Jonge
+ */
+ 
+Language.syntax = [ // C#
+	{ input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote
+	{ input : /\'(.?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>' }, // strings single quote 
+	{ input : /\b(abstract|as|base|break|case|catch|checked|continue|default|delegate|do|else|event|explicit|extern|false|finally|fixed|for|foreach|get|goto|if|implicit|in|interface|internal|is|lock|namespace|new|null|object|operator|out|override|params|partial|private|protected|public|readonly|ref|return|set|sealed|sizeof|static|stackalloc|switch|this|throw|true|try|typeof|unchecked|unsafe|using|value|virtual|while)\b/g, output : '<b>$1</b>' }, // reserved words
+	{ input : /\b(bool|byte|char|class|double|float|int|interface|long|string|struct|void)\b/g, output : '<a>$1</a>' }, // types
+	{ input : /([^:]|^)\/\/(.*?)(<br|<\/P)/g, output : '$1<i>//$2</i>$3' }, // comments //	
+	{ input : /\/\*(.*?)\*\//g, output : '<i>/*$1*/</i>' } // comments /* */
+];
+
+Language.snippets = [];
+
+Language.complete = [ // Auto complete only for 1 character
+	{input : '\'',output : '\'$0\'' },
+	{input : '"', output : '"$0"' },
+	{input : '(', output : '\($0\)' },
+	{input : '[', output : '\[$0\]' },
+	{input : '{', output : '{\n\t$0\n}' }		
+];
+
+Language.shortcuts = [];
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/css.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/css.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,10 @@
+/*
+ * CodePress color styles for CSS syntax highlighting
+ */
+
+b, b a, b u {color:#000080;} /* tags, ids, classes */
+i, i b, i s, i a, i u {color:gray;} /* comments */
+s, s b {color:#a0a0dd;} /* parameters */
+a {color:#0000ff;} /* keys */
+u {color:red;} /* values */
+

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/css.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/css.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,23 @@
+/*
+ * CodePress regular expressions for CSS syntax highlighting
+ */
+
+// CSS
+Language.syntax = [
+	{ input : /(.*?){(.*?)}/g,output : '<b>$1</b>{<u>$2</u>}' }, // tags, ids, classes, values
+	{ input : /([\w-]*?):([^\/])/g,output : '<a>$1</a>:$2' }, // keys
+	{ input : /\((.*?)\)/g,output : '(<s>$1</s>)' }, // parameters
+	{ input : /\/\*(.*?)\*\//g,output : '<i>/*$1*/</i>'} // comments
+]
+
+Language.snippets = []
+
+Language.complete = [
+	{ input : '\'',output : '\'$0\'' },
+	{ input : '"', output : '"$0"' },
+	{ input : '(', output : '\($0\)' },
+	{ input : '[', output : '\[$0\]' },
+	{ input : '{', output : '{\n\t$0\n}' }		
+]
+
+Language.shortcuts = []

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/generic.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/generic.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,9 @@
+/*
+ * CodePress color styles for generic syntax highlighting
+ */
+
+b {color:#7F0055;font-weight:bold;} /* reserved words */
+u {color:darkblue;font-weight:bold;} /* special words */
+i, i b, i s, i u, i em {color:green;font-weight:normal;} /* comments */
+s, s b, s em {color:#2A00FF;font-weight:normal;} /* strings */
+em {font-weight:bold;} /* special chars */
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/generic.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/generic.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,25 @@
+/*
+ * CodePress regular expressions for generic syntax highlighting
+ */
+ 
+// generic languages
+Language.syntax = [
+	{ input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote
+	{ input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>' }, // strings single quote
+	{ input : /\b(abstract|continue|for|new|switch|default|goto|boolean|do|if|private|this|break|double|protected|throw|byte|else|import|public|throws|case|return|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|const|float|while|function|label)\b/g, output : '<b>$1</b>' }, // reserved words
+	{ input : /([\(\){}])/g, output : '<em>$1</em>' }, // special chars;
+	{ input : /([^:]|^)\/\/(.*?)(<br|<\/P)/g, output : '$1<i>//$2</i>$3' }, // comments //
+	{ input : /\/\*(.*?)\*\//g, output : '<i>/*$1*/</i>' } // comments /* */
+]
+
+Language.snippets = []
+
+Language.complete = [
+	{ input : '\'', output : '\'$0\'' },
+	{ input : '"', output : '"$0"' },
+	{ input : '(', output : '\($0\)' },
+	{ input : '[', output : '\[$0\]' },
+	{ input : '{', output : '{\n\t$0\n}' }		
+]
+
+Language.shortcuts = []

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/html.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/html.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,13 @@
+/*
+ * CodePress color styles for HTML syntax highlighting
+ */
+
+b {color:#000080;} /* tags */
+ins, ins b, ins s, ins em {color:gray;} /* comments */
+s, s b {color:#7777e4;} /* attribute values */
+a {color:green;} /* links */
+u {color:#E67300;} /* forms */
+big {color:#db0000;} /* images */
+em, em b {color:#800080;} /* style */
+strong {color:#800000;} /* script */
+tt i {color:darkblue;font-weight:bold;} /* script reserved words */

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/html.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/html.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,59 @@
+/*
+ * CodePress regular expressions for HTML syntax highlighting
+ */
+
+// HTML
+Language.syntax = [
+	{ input : /(&lt;[^!]*?&gt;)/g, output : '<b>$1</b>'	}, // all tags
+	{ input : /(&lt;a .*?&gt;|&lt;\/a&gt;)/g, output : '<a>$1</a>' }, // links
+	{ input : /(&lt;img .*?&gt;)/g, output : '<big>$1</big>' }, // images
+	{ input : /(&lt;\/?(button|textarea|form|input|select|option|label).*?&gt;)/g, output : '<u>$1</u>' }, // forms
+	{ input : /(&lt;style.*?&gt;)(.*?)(&lt;\/style&gt;)/g, output : '<em>$1</em><em>$2</em><em>$3</em>' }, // style tags
+	{ input : /(&lt;script.*?&gt;)(.*?)(&lt;\/script&gt;)/g, output : '<strong>$1</strong><tt>$2</tt><strong>$3</strong>' }, // script tags
+	{ input : /=(".*?")/g, output : '=<s>$1</s>' }, // atributes double quote
+	{ input : /=('.*?')/g, output : '=<s>$1</s>' }, // atributes single quote
+	{ input : /(&lt;!--.*?--&gt.)/g, output : '<ins>$1</ins>' }, // comments 
+	{ input : /\b(alert|window|document|break|continue|do|for|new|this|void|case|default|else|function|return|typeof|while|if|label|switch|var|with|catch|boolean|int|try|false|throws|null|true|goto)\b/g, output : '<i>$1</i>' } // script reserved words 
+]
+
+Language.snippets = [
+	{ input : 'aref', output : '<a href="$0"></a>' },
+	{ input : 'h1', output : '<h1>$0</h1>' },
+	{ input : 'h2', output : '<h2>$0</h2>' },
+	{ input : 'h3', output : '<h3>$0</h3>' },
+	{ input : 'h4', output : '<h4>$0</h4>' },
+	{ input : 'h5', output : '<h5>$0</h5>' },
+	{ input : 'h6', output : '<h6>$0</h6>' },
+	{ input : 'html', output : '<html>\n\t$0\n</html>' },
+	{ input : 'head', output : '<head>\n\t<meta http-equiv="content-type" content="text/html; charset=utf-8" />\n\t<title>$0</title>\n\t\n</head>' },
+	{ input : 'img', output : '<img src="$0" alt="" />' },
+	{ input : 'input', output : '<input name="$0" id="" type="" value="" />' },
+	{ input : 'label', output : '<label for="$0"></label>' },
+	{ input : 'legend', output : '<legend>\n\t$0\n</legend>' },
+	{ input : 'link', output : '<link rel="stylesheet" href="$0" type="text/css" media="screen" charset="utf-8" />' },		
+	{ input : 'base', output : '<base href="$0" />' }, 
+	{ input : 'body', output : '<body>\n\t$0\n</body>' }, 
+	{ input : 'css', output : '<link rel="stylesheet" href="$0" type="text/css" media="screen" charset="utf-8" />' },
+	{ input : 'div', output : '<div>\n\t$0\n</div>' },
+	{ input : 'divid', output : '<div id="$0">\n\t\n</div>' },
+	{ input : 'dl', output : '<dl>\n\t<dt>\n\t\t$0\n\t</dt>\n\t<dd></dd>\n</dl>' },
+	{ input : 'fieldset', output : '<fieldset>\n\t$0\n</fieldset>' },
+	{ input : 'form', output : '<form action="$0" method="" name="">\n\t\n</form>' },
+	{ input : 'meta', output : '<meta name="$0" content="" />' },
+	{ input : 'p', output : '<p>$0</p>' },
+	{ input : 'script', output : '<script type="text/javascript" language="javascript" charset="utf-8">\n\t$0\t\n</script>' },
+	{ input : 'scriptsrc', output : '<script src="$0" type="text/javascript" language="javascript" charset="utf-8"></script>' },
+	{ input : 'span', output : '<span>$0</span>' },
+	{ input : 'table', output : '<table border="$0" cellspacing="" cellpadding="">\n\t<tr><th></th></tr>\n\t<tr><td></td></tr>\n</table>' },
+	{ input : 'style', output : '<style type="text/css" media="screen">\n\t$0\n</style>' }
+]
+	
+Language.complete = [
+	{ input : '\'',output : '\'$0\'' },
+	{ input : '"', output : '"$0"' },
+	{ input : '(', output : '\($0\)' },
+	{ input : '[', output : '\[$0\]' },
+	{ input : '{', output : '{\n\t$0\n}' }		
+]
+
+Language.shortcuts = []

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/java.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/java.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,7 @@
+/*
+ * CodePress color styles for Java syntax highlighting
+ */
+
+b {color:#7F0055;font-weight:bold;font-style:normal;} /* reserved words */
+i, i b, i s {color:#3F7F5F;font-weight:bold;} /* comments */
+s, s b {color:#2A00FF;font-weight:normal;} /* strings */

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/java.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/java.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,24 @@
+/*
+ * CodePress regular expressions for Java syntax highlighting
+ */
+ 
+// Java
+Language.syntax = [
+	{ input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>'}, // strings double quote
+	{ input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>'}, // strings single quote
+	{ input : /\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/g, output : '<b>$1</b>'}, // reserved words
+	{ input : /([^:]|^)\/\/(.*?)(<br|<\/P)/g, output : '$1<i>//$2</i>$3'}, // comments //	
+	{ input : /\/\*(.*?)\*\//g, output : '<i>/*$1*/</i>' }// comments /* */
+]
+
+Language.snippets = []
+
+Language.complete = [
+	{ input : '\'',output : '\'$0\'' },
+	{ input : '"', output : '"$0"' },
+	{ input : '(', output : '\($0\)' },
+	{ input : '[', output : '\[$0\]' },
+	{ input : '{', output : '{\n\t$0\n}' }		
+]
+
+Language.shortcuts = []

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/javascript.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/javascript.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,8 @@
+/*
+ * CodePress color styles for JavaScript syntax highlighting
+ */
+
+b {color:#7F0055;font-weight:bold;} /* reserved words */
+u {color:darkblue;font-weight:bold;} /* special words */
+i, i b, i s, i u {color:green;font-weight:normal;} /* comments */
+s, s b, s u {color:#2A00FF;font-weight:normal;} /* strings */

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/javascript.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/javascript.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,30 @@
+/*
+ * CodePress regular expressions for JavaScript syntax highlighting
+ */
+ 
+// JavaScript
+Language.syntax = [ 
+	{ input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote
+	{ input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>' }, // strings single quote
+	{ input : /\b(break|continue|do|for|new|this|void|case|default|else|function|return|typeof|while|if|label|switch|var|with|catch|boolean|int|try|false|throws|null|true|goto)\b/g, output : '<b>$1</b>' }, // reserved words
+	{ input : /\b(alert|isNaN|parent|Array|parseFloat|parseInt|blur|clearTimeout|prompt|prototype|close|confirm|length|Date|location|Math|document|element|name|self|elements|setTimeout|navigator|status|String|escape|Number|submit|eval|Object|event|onblur|focus|onerror|onfocus|onclick|top|onload|toString|onunload|unescape|open|valueOf|window|onmouseover)\b/g, output : '<u>$1</u>' }, // special words
+	{ input : /([^:]|^)\/\/(.*?)(<br|<\/P)/g, output : '$1<i>//$2</i>$3' }, // comments //
+	{ input : /\/\*(.*?)\*\//g, output : '<i>/*$1*/</i>' } // comments /* */
+]
+
+Language.snippets = [
+	{ input : 'dw', output : 'document.write(\'$0\');' },
+	{ input : 'getid', output : 'document.getElementById(\'$0\')' },
+	{ input : 'fun', output : 'function $0(){\n\t\n}' },
+	{ input : 'func', output : 'function $0(){\n\t\n}' }
+]
+
+Language.complete = [
+	{ input : '\'',output : '\'$0\'' },
+	{ input : '"', output : '"$0"' },
+	{ input : '(', output : '\($0\)' },
+	{ input : '[', output : '\[$0\]' },
+	{ input : '{', output : '{\n\t$0\n}' }		
+]
+
+Language.shortcuts = []

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/perl.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/perl.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,11 @@
+/*
+ * CodePress color styles for Perl syntax highlighting
+ * By J. Nick Koston
+ */
+
+b {color:#7F0055;font-weight:bold;} /* reserved words */
+i, i b, i s, i em, i a, i u {color:gray;font-weight:normal;} /* comments */
+s, s b, s a, s em, s u {color:#2A00FF;font-weight:normal;} /* strings */
+a {color:#006700;font-weight:bold;} /* variables */
+em {color:darkblue;font-weight:bold;} /* functions */
+u {font-weight:bold;} /* special chars */
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/perl.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/perl.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,27 @@
+/*
+ * CodePress regular expressions for Perl syntax highlighting
+ * By J. Nick Koston
+ */
+
+// Perl
+Language.syntax = [ 
+	{ input  : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote
+	{ input  : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>' }, // strings single quote
+	{ input  : /([\$\@\%][\w\.]*)/g, output : '<a>$1</a>' }, // vars
+	{ input  : /(sub\s+)([\w\.]*)/g, output : '$1<em>$2</em>' }, // functions
+	{ input  : /\b(abs|accept|alarm|atan2|bind|binmode|bless|caller|chdir|chmod|chomp|chop|chown|chr|chroot|close|closedir|connect|continue|cos|crypt|dbmclose|dbmopen|defined|delete|die|do|dump|each|else|elsif|endgrent|endhostent|endnetent|endprotoent|endpwent|eof|eval|exec|exists|exit|fcntl|fileno|find|flock|for|foreach|fork|format|formlinegetc|getgrent|getgrgid|getgrnam|gethostbyaddr|gethostbyname|gethostent|getlogin|getnetbyaddr|getnetbyname|getnetent|getpeername|getpgrp|getppid|getpriority|getprotobyname|getprotobynumber|getprotoent|getpwent|getpwnam|getpwuid|getservbyaddr|getservbyname|getservbyport|getservent|getsockname|getsockopt|glob|gmtime|goto|grep|hex|hostname|if|import|index|int|ioctl|join|keys|kill|last|lc|lcfirst|length|link|listen|LoadExternals|local|localtime|log|lstat|map|mkdir|msgctl|msgget|msgrcv|msgsnd|my|next|no|oct|open|opendir|ordpack|package|pipe|pop|pos|print|printf|push|pwd|qq|quotemeta|qw|rand|read|readdir|readlink|recv|redo|ref|rename|require|reset|return|reverse|rewinddir|rindex|rmdir|scalar|seek|seekdir|select|semctl|semget|semop|send|setgrent|sethostent|setnetent|setpgrp|setpriority|setprotoent|setpwent|setservent|setsockopt|shift|shmctl|shmget|shmread|shmwrite|shutdown|sin|sleep|socket|socketpair|sort|splice|split|sprintf|sqrt|srand|stat|stty|study|sub|substr|symlink|syscall|sysopen|sysread|system|syswritetell|telldir|tie|tied|time|times|tr|truncate|uc|ucfirst|umask|undef|unless|unlink|until|unpack|unshift|untie|use|utime|values|vec|waitpid|wantarray|warn|while|write)\b/g, output : '<b>$1</b>' }, // reserved words
+	{ input  : /([\(\){}])/g, output : '<u>$1</u>' }, // special chars
+	{ input  : /#(.*?)(<br>|<\/P>)/g, output : '<i>#$1</i>$2' } // comments
+]
+
+Language.snippets = []
+
+Language.complete = [
+	{ input : '\'',output : '\'$0\'' },
+	{ input : '"', output : '"$0"' },
+	{ input : '(', output : '\($0\)' },
+	{ input : '[', output : '\[$0\]' },
+	{ input : '{', output : '{\n\t$0\n}' }		
+]
+
+Language.shortcuts = []

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/php.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/php.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,12 @@
+/*
+ * CodePress color styles for PHP syntax highlighting
+ */
+
+b {color:#000080;} /* tags */
+big, big b, big em, big ins, big s, strong i, strong i b, strong i s, strong i u, strong i a, strong i a u, strong i s u {color:gray;font-weight:normal;} /* comments */
+s, s b, strong s u, strong s cite {color:#5656fa;font-weight:normal;} /* attributes and strings */
+strong a, strong a u {color:#006700;font-weight:bold;} /* variables */
+em {color:#800080;font-style:normal;} /* style */
+ins {color:#800000;} /* script */
+strong u {color:#7F0055;font-weight:bold;} /* reserved words */
+cite, s cite {color:red;font-weight:bold;} /* <?php and ?> */

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/php.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/php.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,61 @@
+/*
+ * CodePress regular expressions for PHP syntax highlighting
+ */
+
+// PHP
+Language.syntax = [
+	{ input : /(&lt;[^!\?]*?&gt;)/g, output : '<b>$1</b>' }, // all tags
+	{ input : /(&lt;style.*?&gt;)(.*?)(&lt;\/style&gt;)/g, output : '<em>$1</em><em>$2</em><em>$3</em>' }, // style tags
+	{ input : /(&lt;script.*?&gt;)(.*?)(&lt;\/script&gt;)/g, output : '<ins>$1</ins><ins>$2</ins><ins>$3</ins>' }, // script tags
+	{ input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote
+	{ input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>'}, // strings single quote
+	{ input : /(&lt;\?)/g, output : '<strong>$1' }, // <?.*
+	{ input : /(\?&gt;)/g, output : '$1</strong>' }, // .*?>
+	{ input : /(&lt;\?php|&lt;\?=|&lt;\?|\?&gt;)/g, output : '<cite>$1</cite>' }, // php tags
+	{ input : /(\$[\w\.]*)/g, output : '<a>$1</a>' }, // vars
+	{ input : /\b(false|true|and|or|xor|__FILE__|exception|__LINE__|array|as|break|case|class|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|for|foreach|function|global|if|include|include_once|isset|list|new|print|require|require_once|return|static|switch|unset|use|while|__FUNCTION__|__CLASS__|__METHOD__|final|php_user_filter|interface|implements|extends|public|private|protected|abstract|clone|try|catch|throw|this)\b/g, output : '<u>$1</u>' }, // reserved words
+	{ input : /([^:])\/\/(.*?)(<br|<\/P)/g, output : '$1<i>//$2</i>$3' }, // php comments //
+	{ input : /([^:])#(.*?)(<br|<\/P)/g, output : '$1<i>#$2</i>$3' }, // php comments #
+	{ input : /\/\*(.*?)\*\//g, output : '<i>/*$1*/</i>' }, // php comments /* */
+	{ input : /(&lt;!--.*?--&gt.)/g, output : '<big>$1</big>' } // html comments
+]
+
+Language.snippets = [
+	{ input : 'if', output : 'if($0){\n\t\n}' },
+	{ input : 'ifelse', output : 'if($0){\n\t\n}\nelse{\n\t\n}' },
+	{ input : 'else', output : '}\nelse {\n\t' },
+	{ input : 'elseif', output : '}\nelseif($0) {\n\t' },
+	{ input : 'do', output : 'do{\n\t$0\n}\nwhile();' },
+	{ input : 'inc', output : 'include_once("$0");' },
+	{ input : 'fun', output : 'function $0(){\n\t\n}' },	
+	{ input : 'func', output : 'function $0(){\n\t\n}' },	
+	{ input : 'while', output : 'while($0){\n\t\n}' },
+	{ input : 'for', output : 'for($0,,){\n\t\n}' },
+	{ input : 'fore', output : 'foreach($0 as ){\n\t\n}' },
+	{ input : 'foreach', output : 'foreach($0 as ){\n\t\n}' },
+	{ input : 'echo', output : 'echo \'$0\';' },
+	{ input : 'switch', output : 'switch($0) {\n\tcase "": break;\n\tdefault: ;\n}' },
+	{ input : 'case', output : 'case "$0" : break;' },
+	{ input : 'ret0', output : 'return false;' },
+	{ input : 'retf', output : 'return false;' },
+	{ input : 'ret1', output : 'return true;' },
+	{ input : 'rett', output : 'return true;' },
+	{ input : 'ret', output : 'return $0;' },
+	{ input : 'def', output : 'define(\'$0\',\'\');' },
+	{ input : '<?', output : 'php\n$0\n?>' }
+]
+
+Language.complete = [
+	{ input : '\'', output : '\'$0\'' },
+	{ input : '"', output : '"$0"' },
+	{ input : '(', output : '\($0\)' },
+	{ input : '[', output : '\[$0\]' },
+	{ input : '{', output : '{\n\t$0\n}' }		
+]
+
+Language.shortcuts = [
+	{ input : '[space]', output : '&nbsp;' },
+	{ input : '[enter]', output : '<br />' } ,
+	{ input : '[j]', output : 'testing' },
+	{ input : '[7]', output : '&amp;' }
+]
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/ruby.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/ruby.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,10 @@
+/*
+ * CodePress color styles for Ruby syntax highlighting
+ */
+
+b {color:#7F0055;font-weight:bold;} /* reserved words */
+i, i b, i s, i em, i a, i u {color:gray;font-weight:normal;} /* comments */
+s, s b, s a, s em, s u {color:#2A00FF;font-weight:normal;} /* strings */
+a {color:#006700;font-weight:bold;} /* variables */
+em {color:darkblue;font-weight:bold;} /* functions */
+u {font-weight:bold;} /* special chars */
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/ruby.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/ruby.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,26 @@
+/*
+ * CodePress regular expressions for Perl syntax highlighting
+ */
+
+// Ruby
+Language.syntax = [
+	{ input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, // strings double quote 
+	{ input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<s>\'$1$2</s>' }, // strings single quote
+	{ input : /([\$\@\%]+)([\w\.]*)/g, output : '<a>$1$2</a>' }, // vars
+	{ input : /(def\s+)([\w\.]*)/g, output : '$1<em>$2</em>' }, // functions
+	{ input : /\b(alias|and|BEGIN|begin|break|case|class|def|defined|do|else|elsif|END|end|ensure|false|for|if|in|module|next|nil|not|or|redo|rescue|retry|return|self|super|then|true|undef|unless|until|when|while|yield)\b/g, output : '<b>$1</b>' }, // reserved words
+	{ input  : /([\(\){}])/g, output : '<u>$1</u>' }, // special chars
+	{ input  : /#(.*?)(<br>|<\/P>)/g, output : '<i>#$1</i>$2' } // comments
+];
+
+Language.snippets = []
+
+Language.complete = [
+	{ input : '\'',output : '\'$0\'' },
+	{ input : '"', output : '"$0"' },
+	{ input : '(', output : '\($0\)' },
+	{ input : '[', output : '\[$0\]' },
+	{ input : '{', output : '{\n\t$0\n}' }		
+]
+
+Language.shortcuts = []

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/sql.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/sql.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,10 @@
+/*
+ * CodePress color styles for SQL syntax highlighting
+ * By Merlin Moncure
+ */
+ 
+b {color:#0000FF;font-style:normal;font-weight:bold;} /* reserved words */
+u {color:#FF0000;font-style:normal;} /* types */
+a {color:#CD6600;font-style:normal;font-weight:bold;} /* commands */
+i, i b, i u, i a, i s  {color:#A9A9A9;font-weight:normal;font-style:italic;} /* comments */
+s, s b, s u, s a, s i {color:#2A00FF;font-weight:normal;} /* strings */

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/sql.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/sql.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,30 @@
+/*
+ * CodePress regular expressions for SQL syntax highlighting
+ * By Merlin Moncure
+ */
+ 
+// SQL
+Language.syntax = [
+	{ input : /\'(.*?)(\')/g, output : '<s>\'$1$2</s>' }, // strings single quote
+	{ input : /\b(add|after|aggregate|alias|all|and|as|authorization|between|by|cascade|cache|cache|called|case|check|column|comment|constraint|createdb|createuser|cycle|database|default|deferrable|deferred|diagnostics|distinct|domain|each|else|elseif|elsif|encrypted|except|exception|for|foreign|from|from|full|function|get|group|having|if|immediate|immutable|in|increment|initially|increment|index|inherits|inner|input|intersect|into|invoker|is|join|key|language|left|like|limit|local|loop|match|maxvalue|minvalue|natural|nextval|no|nocreatedb|nocreateuser|not|null|of|offset|oids|on|only|operator|or|order|outer|owner|partial|password|perform|plpgsql|primary|record|references|replace|restrict|return|returns|right|row|rule|schema|security|sequence|session|sql|stable|statistics|table|temp|temporary|then|time|to|transaction|trigger|type|unencrypted|union|unique|user|using|valid|value|values|view|volatile|when|where|with|without|zone)\b/gi, output : '<b>$1</b>' }, // reserved words
+	{ input : /\b(bigint|bigserial|bit|boolean|box|bytea|char|character|cidr|circle|date|decimal|double|float4|float8|inet|int2|int4|int8|integer|interval|line|lseg|macaddr|money|numeric|oid|path|point|polygon|precision|real|refcursor|serial|serial4|serial8|smallint|text|timestamp|varbit|varchar)\b/gi, output : '<u>$1</u>' }, // types
+	{ input : /\b(abort|alter|analyze|begin|checkpoint|close|cluster|comment|commit|copy|create|deallocate|declare|delete|drop|end|execute|explain|fetch|grant|insert|listen|load|lock|move|notify|prepare|reindex|reset|restart|revoke|rollback|select|set|show|start|truncate|unlisten|update)\b/gi, output : '<a>$1</a>' }, // commands
+	{ input : /([^:]|^)\-\-(.*?)(<br|<\/P)/g, output: '$1<i>--$2</i>$3' } // comments //	
+]
+
+Language.snippets = [
+	{ input : 'select', output : 'select $0 from  where ' }
+]
+
+Language.complete = [
+	{ input : '\'', output : '\'$0\'' },
+	{ input : '"', output : '"$0"' },
+	{ input : '(', output : '\($0\)' },
+	{ input : '[', output : '\[$0\]' },
+	{ input : '{', output : '{\n\t$0\n}' }		
+]
+
+Language.shortcuts = []
+
+
+

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/text.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/text.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,5 @@
+/*
+ * CodePress color styles for Text syntax highlighting
+ */
+
+/* do nothing as expected */

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/text.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/text.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,9 @@
+/*
+ * CodePress regular expressions for Text syntax highlighting
+ */
+
+// plain text
+Language.syntax = []
+Language.snippets = []
+Language.complete = []
+Language.shortcuts = []

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/vbscript.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/vbscript.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,71 @@
+/*
+ * CodePress color styles for ASP-VB syntax highlighting 
+ * By Martin D. Kirk
+ */
+
+/* tags */
+b {
+	color:#000080;
+} 
+/* comments */
+big, big b, big em, big ins, big s, strong i, strong i b, strong i s, strong i u, strong i a, strong i a u, strong i s u {
+	color:gray;
+	font-weight:normal;
+}
+/* ASP comments */
+strong dfn, strong dfn a,strong dfn var, strong dfn a u, strong dfn u{
+	color:gray;
+	font-weight:normal;
+}
+ /* attributes */ 
+s, s b, span s u, span s cite, strong span s {
+	color:#5656fa ;
+	font-weight:normal;
+}
+ /* strings */ 
+strong s,strong s b, strong s u, strong s cite {
+	color:#009900;
+	font-weight:normal;
+}
+strong ins{
+	color:#000000;
+	font-weight:bold;
+}
+ /* Syntax */
+strong a, strong a u {
+	color:#0000FF;
+	font-weight:;
+}
+ /* Native Keywords */
+strong u {
+	color:#990099;
+	font-weight:bold;
+}
+/* Numbers */
+strong var{
+	color:#FF0000;
+}
+/* ASP Language */
+span{
+	color:#990000;
+	font-weight:bold;
+}
+strong i,strong a i, strong u i {
+	color:#009999;
+}
+/* style */
+em {
+	color:#800080;
+	font-style:normal;
+}
+ /* script */ 
+ins {
+	color:#800000;
+	font-weight:bold;
+}
+
+/* <?php and ?> */
+cite, s cite {
+	color:red;
+	font-weight:bold;
+}
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/vbscript.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/vbscript.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,117 @@
+/*
+ * CodePress regular expressions for ASP-vbscript syntax highlighting
+ */
+
+// ASP VBScript
+Language.syntax = [
+// all tags
+	{ input : /(&lt;[^!%|!%@]*?&gt;)/g, output : '<b>$1</b>' }, 
+// style tags	
+	{ input : /(&lt;style.*?&gt;)(.*?)(&lt;\/style&gt;)/g, output : '<em>$1</em><em>$2</em><em>$3</em>' }, 
+// script tags	
+	{ input : /(&lt;script.*?&gt;)(.*?)(&lt;\/script&gt;)/g, output : '<ins>$1</ins><ins>$2</ins><ins>$3</ins>' }, 
+// strings "" and attributes
+	{ input : /\"(.*?)(\"|<br>|<\/P>)/g, output : '<s>"$1$2</s>' }, 
+// ASP Comment
+	{ input : /\'(.*?)(\'|<br>|<\/P>)/g, output : '<dfn>\'$1$2</dfn>'}, 
+// <%.*
+	{ input : /(&lt;%)/g, output : '<strong>$1' }, 
+// .*%>	
+	{ input : /(%&gt;)/g, output : '$1</strong>' }, 
+// <%@...%>	
+	{ input : /(&lt;%@)(.+?)(%&gt;)/gi, output : '$1<span>$2</span>$3' }, 
+//Numbers	
+	{ input : /\b([\d]+)\b/g, output : '<var>$1</var>' }, 
+// Reserved Words 1 (Blue)
+	{ input : /\b(And|As|ByRef|ByVal|Call|Case|Class|Const|Dim|Do|Each|Else|ElseIf|Empty|End|Eqv|Exit|False|For|Function)\b/gi, output : '<a>$1</a>' }, 
+	{ input : /\b(Get|GoTo|If|Imp|In|Is|Let|Loop|Me|Mod|Enum|New|Next|Not|Nothing|Null|On|Option|Or|Private|Public|ReDim|Rem)\b/gi, output : '<a>$1</a>' }, 
+	{ input : /\b(Resume|Select|Set|Stop|Sub|Then|To|True|Until|Wend|While|With|Xor|Execute|Randomize|Erase|ExecuteGlobal|Explicit|step)\b/gi, output : '<a>$1</a>' }, 
+// Reserved Words 2 (Purple)	
+	{ input : /\b(Abandon|Abs|AbsolutePage|AbsolutePosition|ActiveCommand|ActiveConnection|ActualSize|AddHeader|AddNew|AppendChunk)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(AppendToLog|Application|Array|Asc|Atn|Attributes|BeginTrans|BinaryRead|BinaryWrite|BOF|Bookmark|Boolean|Buffer|Byte)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(CacheControl|CacheSize|Cancel|CancelBatch|CancelUpdate|CBool|CByte|CCur|CDate|CDbl|Charset|Chr|CInt|Clear)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(ClientCertificate|CLng|Clone|Close|CodePage|CommandText|CommandType|CommandTimeout|CommitTrans|CompareBookmarks|ConnectionString|ConnectionTimeout)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Contents|ContentType|Cookies|Cos|CreateObject|CreateParameter|CSng|CStr|CursorLocation|CursorType|DataMember|DataSource|Date|DateAdd|DateDiff)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(DatePart|DateSerial|DateValue|Day|DefaultDatabase|DefinedSize|Delete|Description|Double|EditMode|Eof|EOF|err|Error)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Exp|Expires|ExpiresAbsolute|Filter|Find|Fix|Flush|Form|FormatCurrency|FormatDateTime|FormatNumber|FormatPercent)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(GetChunk|GetLastError|GetRows|GetString|Global|HelpContext|HelpFile|Hex|Hour|HTMLEncode|IgnoreCase|Index|InStr|InStrRev)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Int|Integer|IsArray|IsClientConnected|IsDate|IsolationLevel|Join|LBound|LCase|LCID|Left|Len|Lock|LockType|Log|Long|LTrim)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(MapPath|MarshalOptions|MaxRecords|Mid|Minute|Mode|Month|MonthName|Move|MoveFirst|MoveLast|MoveNext|MovePrevious|Name|NextRecordset)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Now|Number|NumericScale|ObjectContext|Oct|Open|OpenSchema|OriginalValue|PageCount|PageSize|Pattern|PICS|Precision|Prepared|Property)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Provider|QueryString|RecordCount|Redirect|RegExp|Remove|RemoveAll|Replace|Requery|Request|Response|Resync|Right|Rnd)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(RollbackTrans|RTrim|Save|ScriptTimeout|Second|Seek|Server|ServerVariables|Session|SessionID|SetAbort|SetComplete|Sgn)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(Sin|Size|Sort|Source|Space|Split|Sqr|State|StaticObjects|Status|StayInSync|StrComp|String|StrReverse|Supports|Tan|Time)\b/gi, output : '<u>$1</u>' },
+	{ input : /\b(Timeout|Timer|TimeSerial|TimeValue|TotalBytes|Transfer|Trim|Type|Type|UBound|UCase|UnderlyingValue|UnLock|Update|UpdateBatch)\b/gi, output : '<u>$1</u>' }, 
+	{ input : /\b(URLEncode|Value|Value|Version|Weekday|WeekdayName|Write|Year)\b/gi, output : '<u>$1</u>' }, 
+// Reserved Words 3 (Turquis)
+	{ input : /\b(vbBlack|vbRed|vbGreen|vbYellow|vbBlue|vbMagenta|vbCyan|vbWhite|vbBinaryCompare|vbTextCompare)\b/gi, output : '<i>$1</i>' }, 
+  	{ input : /\b(vbSunday|vbMonday|vbTuesday|vbWednesday|vbThursday|vbFriday|vbSaturday|vbUseSystemDayOfWeek)\b/gi, output : '<i>$1</i>' }, 
+	{ input : /\b(vbFirstJan1|vbFirstFourDays|vbFirstFullWeek|vbGeneralDate|vbLongDate|vbShortDate|vbLongTime|vbShortTime)\b/gi, output : '<i>$1</i>' }, 
+	{ input : /\b(vbObjectError|vbCr|VbCrLf|vbFormFeed|vbLf|vbNewLine|vbNullChar|vbNullString|vbTab|vbVerticalTab|vbUseDefault|vbTrue)\b/gi, output : '<i>$1</i>' }, 
+	{ input : /\b(vbFalse|vbEmpty|vbNull|vbInteger|vbLong|vbSingle|vbDouble|vbCurrency|vbDate|vbString|vbObject|vbError|vbBoolean|vbVariant)\b/gi, output : '<i>$1</i>' }, 
+	{ input : /\b(vbDataObject|vbDecimal|vbByte|vbArray)\b/gi, output : '<i>$1</i>' },
+// html comments
+	{ input : /(&lt;!--.*?--&gt.)/g, output : '<big>$1</big>' } 
+]
+
+Language.Functions = [ 
+  	// Output at index 0, must be the desired tagname surrounding a $1
+	// Name is the index from the regex that marks the functionname
+	{input : /(function|sub)([ ]*?)(\w+)([ ]*?\()/gi , output : '<ins>$1</ins>', name : '$3'}
+]
+
+Language.snippets = [
+//Conditional
+	{ input : 'if', output : 'If $0 Then\n\t\nEnd If' },
+	{ input : 'ifelse', output : 'If $0 Then\n\t\n\nElse\n\t\nEnd If' },
+	{ input : 'case', output : 'Select Case $0\n\tCase ?\n\tCase Else\nEnd Select'},
+//Response
+	{ input : 'rw', output : 'Response.Write( $0 )' },
+	{ input : 'resc', output : 'Response.Cookies( $0 )' },
+	{ input : 'resb', output : 'Response.Buffer'},
+	{ input : 'resflu', output : 'Response.Flush()'},
+	{ input : 'resend', output : 'Response.End'},
+//Request
+	{ input : 'reqc', output : 'Request.Cookies( $0 )' },
+	{ input : 'rq', output : 'Request.Querystring("$0")' },
+	{ input : 'rf', output : 'Request.Form("$0")' },
+//FSO
+	{ input : 'fso', output : 'Set fso = Server.CreateObject("Scripting.FileSystemObject")\n$0' },
+	{ input : 'setfo', output : 'Set fo = fso.getFolder($0)' },
+	{ input : 'setfi', output : 'Set fi = fso.getFile($0)' },
+	{ input : 'twr', output : 'Set f = fso.CreateTextFile($0,true)\'overwrite\nf.WriteLine()\nf.Close'},
+	{ input : 'tre', output : 'Set f = fso.OpenTextFile($0, 1)\nf.ReadAll\nf.Close'},
+//Server
+	{ input : 'mapp', output : 'Server.Mappath($0)' },
+//Loops
+	{ input : 'foreach', output : 'For Each $0 in ?\n\t\nNext' },
+	{ input : 'for', output : 'For $0 to ? step ?\n\t\nNext' },
+	{ input : 'do', output : 'Do While($0)\n\t\nLoop' },
+	{ input : 'untilrs', output : 'do until rs.eof\n\t\nrs.movenext\nloop' },
+//ADO
+	{ input : 'adorec', output : 'Set rs = Server.CreateObject("ADODB.Recordset")' },
+	{ input : 'adocon', output : 'Set Conn = Server.CreateObject("ADODB.Connection")' },
+	{ input : 'adostr', output : 'Set oStr = Server.CreateObject("ADODB.Stream")' },
+//Http Request
+	{ input : 'xmlhttp', output : 'Set xmlHttp = Server.CreateObject("Microsoft.XMLHTTP")\nxmlHttp.open("GET", $0, false)\nxmlHttp.send()\n?=xmlHttp.responseText' },
+	{ input : 'xmldoc', output : 'Set xmldoc = Server.CreateObject("Microsoft.XMLDOM")\nxmldoc.async=false\nxmldoc.load(request)'},
+//Functions
+	{ input : 'func', output : 'Function $0()\n\t\n\nEnd Function'},
+	{ input : 'sub', output : 'Sub $0()\n\t\nEnd Sub'}
+
+]
+
+Language.complete = [
+	//{ input : '\'', output : '\'$0\'' },
+	{ input : '"', output : '"$0"' },
+	{ input : '(', output : '\($0\)' },
+	{ input : '[', output : '\[$0\]' },
+	{ input : '{', output : '{\n\t$0\n}' }		
+]
+
+Language.shortcuts = [
+	{ input : '[space]', output : '&nbsp;' },
+	{ input : '[enter]', output : '<br />' } ,
+	{ input : '[j]', output : 'testing' },
+	{ input : '[7]', output : '&amp;' }
+]
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/xsl.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/xsl.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,15 @@
+/*
+ * CodePress color styles for HTML syntax highlighting
+ * By RJ Bruneel
+ */
+ 
+b {color:#000080;} /* tags */
+ins, ins b, ins s, ins em {color:gray;} /* comments */
+s, s b {color:#7777e4;} /* attribute values */
+a {color:#E67300;} /* links */
+u {color:#CC66CC;} /* forms */
+big {color:#db0000;} /* images */
+em, em b {color:#800080;} /* style */
+strong {color:#800000;} /* script */
+tt i {color:darkblue;font-weight:bold;} /* script reserved words */
+xsl {color:green;} /* xsl */

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/xsl.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/codepress/languages/xsl.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,103 @@
+/*
+ * CodePress regular expressions for XSL syntax highlighting
+ * By RJ Bruneel
+ */
+
+Language.syntax = [ // XSL
+	{
+	input : /(&lt;[^!]*?&gt;)/g,
+	output : '<b>$1</b>' // all tags
+	},{
+	input : /(&lt;a.*?&gt;|&lt;\/a&gt;)/g,
+	output : '<a>$1</a>' // links
+	},{
+	input : /(&lt;img .*?&gt;)/g,
+	output : '<big>$1</big>' // images
+	},{
+	input : /(&lt;\/?(button|textarea|form|input|select|option|label).*?&gt;)/g,
+	output : '<u>$1</u>' // forms
+	},{
+	input : /(&lt;style.*?&gt;)(.*?)(&lt;\/style&gt;)/g,
+	output : '<em>$1</em><em>$2</em><em>$3</em>' // style tags
+	},{
+	input : /(&lt;script.*?&gt;)(.*?)(&lt;\/script&gt;)/g,
+	output : '<strong>$1</strong><tt>$2</tt><strong>$3</strong>' // script tags
+	},{	
+	input : /(&lt;xsl.*?&gt;|&lt;\/xsl.*?&gt;)/g,
+	output : '<xsl>$1</xsl>' // xsl
+	},{
+	input : /=(".*?")/g,
+	output : '=<s>$1</s>' // atributes double quote
+	},{
+	input : /=('.*?')/g,
+	output : '=<s>$1</s>' // atributes single quote
+	},{
+	input : /(&lt;!--.*?--&gt.)/g,
+	output : '<ins>$1</ins>' // comments 
+	},{
+	input : /\b(alert|window|document|break|continue|do|for|new|this|void|case|default|else|function|return|typeof|while|if|label|switch|var|with|catch|boolean|int|try|false|throws|null|true|goto)\b/g,
+	output : '<i>$1</i>' // script reserved words
+	}
+];
+
+Language.snippets = [
+	{input : 'aref', output : '<a href="$0"></a>' },
+	{input : 'h1', output : '<h1>$0</h1>' },
+	{input : 'h2', output : '<h2>$0</h2>' },
+	{input : 'h3', output : '<h3>$0</h3>' },
+	{input : 'h4', output : '<h4>$0</h4>' },
+	{input : 'h5', output : '<h5>$0</h5>' },
+	{input : 'h6', output : '<h6>$0</h6>' },
+	{input : 'html', output : '<html>\n\t$0\n</html>' },
+	{input : 'head', output : '<head>\n\t<meta http-equiv="content-type" content="text/html; charset=utf-8" />\n\t<title>$0</title>\n\t\n</head>' },
+	{input : 'img', output : '<img src="$0" width="" height="" alt="" border="0" />' },
+	{input : 'input', output : '<input name="$0" id="" type="" value="" />' },
+	{input : 'label', output : '<label for="$0"></label>' },
+	{input : 'legend', output : '<legend>\n\t$0\n</legend>' },
+	{input : 'link', output : '<link rel="stylesheet" href="$0" type="text/css" media="screen" charset="utf-8" />' },		
+	{input : 'base', output : '<base href="$0" />' }, 
+	{input : 'body', output : '<body>\n\t$0\n</body>' }, 
+	{input : 'css', output : '<link rel="stylesheet" href="$0" type="text/css" media="screen" charset="utf-8" />' },
+	{input : 'div', output : '<div>\n\t$0\n</div>' },
+	{input : 'divid', output : '<div id="$0">\n\t\n</div>' },
+	{input : 'dl', output : '<dl>\n\t<dt>\n\t\t$0\n\t</dt>\n\t<dd></dd>\n</dl>' },
+	{input : 'fieldset', output : '<fieldset>\n\t$0\n</fieldset>' },
+	{input : 'form', output : '<form action="$0" method="" name="">\n\t\n</form>' },
+	{input : 'meta', output : '<meta name="$0" content="" />' },
+	{input : 'p', output : '<p>$0</p>' },
+	{input : 'b', output : '<b>$0</b>' },
+	{input : 'li', output : '<li>$0</li>' },
+	{input : 'ul', output : '<ul>$0</ul>' },
+	{input : 'ol', output : '<ol>$0</ol>' },
+	{input : 'strong', output : '<strong>$0</strong>' },
+	{input : 'br', output : '<br />' },
+	{input : 'script', output : '<script type="text/javascript" language="javascript" charset="utf-8">\n\t$0\t\n</script>' },
+	{input : 'scriptsrc', output : '<script src="$0" type="text/javascript" language="javascript" charset="utf-8"></script>' },
+	{input : 'span', output : '<span>$0</span>' },
+	{input : 'table', output : '<table border="$0" cellspacing="" cellpadding="">\n\t<tr><th></th></tr>\n\t<tr><td></td></tr>\n</table>' },
+	{input : 'style', output : '<style type="text/css" media="screen">\n\t$0\n</style>' },
+	{input : 'xsl:stylesheet', output : '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">' },
+	{input : 'xsl:template', output : '<xsl:template>$0</xsl:template>' },
+	{input : 'xsl:for-each', output : '<xsl:for-each select="$0"></xsl:for-each>' },
+	{input : 'xsl:choose', output : '<xsl:choose>$0<\xsl:choose>' },
+	{input : 'xsl:param', output : '<xsl:param name="$0" />' },
+	{input : 'xsl:variable', output : '<xsl:variable name="$0"></xsl:variable>' },
+	{input : 'xsl:if', output : '<xsl:if test="$0"></xsl:if>' },
+	{input : 'xsl:when', output : '<xsl:when test="$0"></xsl:when>' },
+	{input : 'xsl:otherwise', output : '<xsl:otherwise>$0</xsl:otherwise>' },
+	{input : 'xsl:attribute', output : '<xsl:attribute name="$0"></xsl:attribute>' },
+	{input : 'xsl:value-of', output : '<xsl:value-of select="$0"/>' },
+	{input : 'xsl:with-param', output : '<xsl:with-param name="$0" select="" />' },
+	{input : 'xsl:call-template', output : '<xsl:call-template name="$0">' }
+
+];
+	
+Language.complete = [ // Auto complete only for 1 character
+	{input : '\'',output : '\'$0\'' },
+	{input : '"', output : '"$0"' },
+	{input : '(', output : '\($0\)' },
+	{input : '[', output : '\[$0\]' },
+	{input : '{', output : '{\n\t$0\n}' }		
+];
+
+Language.shortcuts = [];
\ No newline at end of file

Added: jifty/branches/autoversioning/plugins/CodePress/share/web/static/js/codepress.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/plugins/CodePress/share/web/static/js/codepress.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,171 @@
+/*
+ * CodePress - Real Time Syntax Highlighting Editor written in JavaScript - http://codepress.org/
+ * 
+ * Copyright (C) 2006 Fernando M.A.d.S. <fermads at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the 
+ * GNU Lesser General Public License as published by the Free Software Foundation.
+ * 
+ * Read the full licence: http://www.opensource.org/licenses/lgpl-license.php
+ *
+ * This version is locally modified for Jifty, see Jifty::Plugin::CodePress
+ */
+
+CodePress = function(obj) {
+	var self = document.createElement('iframe');
+	self.textarea = obj;
+	self.textarea.disabled = true;
+	self.textarea.style.overflow = 'hidden';
+	self.style.height = self.textarea.clientHeight +'px';
+	self.style.width = self.textarea.clientWidth +'px';
+	self.textarea.style.overflow = 'auto';
+	self.style.border = '1px solid gray';
+	self.frameBorder = 0; // remove IE internal iframe border
+	self.style.visibility = 'hidden';
+	self.style.position = 'absolute';
+	self.options = self.textarea.className;
+	
+	self.initialize = function() {
+		self.editor = self.contentWindow.CodePress;
+		self.editor.body = self.contentWindow.document.getElementsByTagName('body')[0];
+		self.editor.setCode(self.textarea.value);
+		self.setOptions();
+		self.editor.syntaxHighlight('init');
+		self.textarea.style.display = 'none';
+		self.style.position = 'static';
+		self.style.visibility = 'visible';
+		self.style.display = 'inline';
+
+		// where blur event is delivered?
+		var iframe = self;
+		if (self.contentDocument) {          // For NS6
+			iframe = self.contentDocument;
+		} else if (self.contentWindow) {     // For IE5.5 and IE6
+			//iframe = self.contentWindow.document;
+		} else if (self.document) {          // For IE5
+			iframe = self.document;
+		} else {
+			alert("can't find frame");
+		}
+
+		DOM.Events.addListener( iframe, 'blur', function () {
+			self.textarea.value = self.getCode();
+			self.textarea.disabled = false;
+			return self;
+		});
+		DOM.Events.addListener( iframe, 'focus', function () {
+			self.textarea.disabled = true;
+			return self;
+		});
+	}
+	
+	// obj can by a textarea id or a string (code)
+	self.edit = function(obj,language) {
+		if(obj) self.textarea.value = document.getElementById(obj) ? document.getElementById(obj).value : obj;
+		if(!self.textarea.disabled) return;
+		self.language = language ? language : self.getLanguage();
+		self.src = '/static/codepress/codepress.html?language='+self.language+'&ts='+(new Date).getTime();
+		//if(self.attachEvent) self.attachEvent('onload',self.initialize);
+		//else self.addEventListener('load',self.initialize,false);
+		DOM.Events.addListener(self, 'load', self.initialize);
+	}
+
+	self.getLanguage = function() {
+		for (language in CodePress.languages) 
+			if(self.options.match('\\b'+language+'\\b')) 
+				return CodePress.languages[language] ? language : 'generic';
+		return 'generic';
+	}
+	
+	self.setOptions = function() {
+		if(self.options.match('autocomplete-off')) self.toggleAutoComplete();
+		if(self.options.match('readonly-on')) self.toggleReadOnly();
+		if(self.options.match('linenumbers-off')) self.toggleLineNumbers();
+	}
+	
+	self.getCode = function() {
+		return self.textarea.disabled ? self.editor.getCode() : self.textarea.value;
+	}
+
+	self.setCode = function(code) {
+		self.textarea.disabled ? self.editor.setCode(code) : self.textarea.value = code;
+	}
+
+	self.toggleAutoComplete = function() {
+		self.editor.autocomplete = (self.editor.autocomplete) ? false : true;
+	}
+	
+	self.toggleReadOnly = function() {
+		self.textarea.readOnly = (self.textarea.readOnly) ? false : true;
+		if(self.style.display != 'none') // prevent exception on FF + iframe with display:none
+			self.editor.readOnly(self.textarea.readOnly ? true : false);
+	}
+	
+	self.toggleLineNumbers = function() {
+		var cn = self.editor.body.className;
+		self.editor.body.className = (cn==''||cn=='show-line-numbers') ? 'hide-line-numbers' : 'show-line-numbers';
+	}
+	
+	self.toggleEditor = function() {
+		if(self.textarea.disabled) {
+			self.textarea.value = self.getCode();
+			self.textarea.disabled = false;
+			self.style.display = 'none';
+			self.textarea.style.display = 'inline';
+		}
+		else {
+			self.textarea.disabled = true;
+			self.setCode(self.textarea.value);
+			self.editor.syntaxHighlight('init');
+			self.style.display = 'inline';
+			self.textarea.style.display = 'none';
+		}
+	}
+
+	self.edit();
+	return self;
+}
+
+CodePress.languages = {	
+	csharp : 'C#', 
+	css : 'CSS', 
+	generic : 'Generic',
+	html : 'HTML',
+	java : 'Java', 
+	javascript : 'JavaScript', 
+	perl : 'Perl', 
+	ruby : 'Ruby',	
+	php : 'PHP', 
+	text : 'Text', 
+	sql : 'SQL',
+	vbscript : 'VBScript'
+}
+
+CodePress.instances = {}
+
+CodePress.run = function() {
+	t = document.getElementsByTagName('textarea');
+	for(var i=0,n=t.length;i<n;i++) {
+		if(t[i].className.match('codepress')) {
+			id = t[i].id;
+			//t[i].id = id+'_cp';
+			CodePress.instances[id] = new CodePress(t[i]);
+			t[i].parentNode.insertBefore(CodePress.instances[id], t[i]);
+		} 
+	}
+}
+
+CodePress.beforeSubmit = function() {
+	for (instance in CodePress.instances)  {
+		// consider just Jifty fields
+		if ( instance.substr(0,5) == 'J:A:F' ) {
+			CodePress.instances[ instance ].toggleEditor();
+		}
+	}
+}
+
+//if(window.attachEvent) window.attachEvent('onload',CodePress.run);
+//else window.addEventListener('DOMContentLoaded',CodePress.run,false);
+//DOM.Events.addListener(window, "load", CodePress.run);
+// Jifty-specific onLoad hook
+onLoadHook( 'CodePress.run();' );

Modified: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/AdminUI/web/templates/__jifty/admin/index.html
==============================================================================
--- jifty/branches/autoversioning/share/plugins/Jifty/Plugin/AdminUI/web/templates/__jifty/admin/index.html	(original)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/AdminUI/web/templates/__jifty/admin/index.html	Sun Jul 22 21:13:55 2007
@@ -19,7 +19,7 @@
 <h2><% _('Actions') %></h2>
 <ul>
 % foreach my $action (Jifty->api->actions) {
-% Jifty::Util->require($action);
+% next unless (Jifty::Util->try_to_require($action));
 % next if ( $action->can('autogenerated') and $action->autogenerated);
 <li><% Jifty->web->link( url => '/__jifty/admin/action/'.$action, label => $action) %></li>
 % }

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/GoogleMap/web/static/css/google_map.css
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/GoogleMap/web/static/css/google_map.css	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,15 @@
+/* XXX: move to Plugin::GoogleMap */
+
+div .googlemap-search-results {
+    background-color:white;
+    border-width: 2px;
+    border-color: black;
+    border-style:dashed;
+    display:none;
+    height:450px;
+    left:50px;
+    position:relative;
+    top:-300px;
+    width:250px;
+    z-index:10;
+}

Added: jifty/branches/autoversioning/share/plugins/Jifty/Plugin/GoogleMap/web/static/js/google_map.js
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/plugins/Jifty/Plugin/GoogleMap/web/static/js/google_map.js	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,196 @@
+// XXX: move me to Plugin/GoogleMap's share when that works
+
+if (GMap2) {
+    //document.body.onunload = "GUnload()";
+
+if ( typeof Jifty == 'undefined' ) {
+    Jifty = {}
+}
+
+Jifty.GMap = function() {};
+Jifty.GMap.location_editor = function(element, x, y, xid, yid, zoom_level, no_marker, readonly) {
+    if (!GBrowserIsCompatible())
+	return;
+
+    var map = new GMap2(element);
+    map.enableScrollWheelZoom();
+    map._jifty_search_result = element.nextSibling;
+    map.addControl(new GSmallZoomControl());
+    if(!readonly)
+	map.addControl(new EditLocationControl());
+    map.setCenter(new GLatLng(y, x), zoom_level);
+    map._jifty_form_x = xid;
+    map._jifty_form_y = yid;
+    if (!no_marker) {
+	map._jifty_location = new GMarker(new GLatLng(y, x));
+	map.addOverlay(map._jifty_location);
+    }
+    GEvent.addListener(map, "click", function(marker, point) {
+	if (!marker && map._jifty_edit_control.editing) {
+	    map.removeOverlay(map._jifty_location);
+	    map._jifty_location = new GMarker(point)
+	    map.addOverlay(map._jifty_location);
+	}});
+}
+
+// TODO: separate edit location control and location search control
+
+function EditLocationControl() {}
+EditLocationControl.prototype = new GControl();
+
+EditLocationControl.prototype.initialize = function(map) {
+  var container = document.createElement("div");
+
+  var EditDiv = document.createElement("div");
+  this.setButtonStyle_(EditDiv);
+  EditDiv.appendChild(document.createTextNode("Edit"));
+
+  var CancelDiv = document.createElement("div");
+  this.setButtonStyle_(CancelDiv);
+  CancelDiv.appendChild(document.createTextNode("Cancel"));
+
+  var SearchDiv = document.createElement("div");
+  this.setButtonStyle_(SearchDiv);
+  SearchDiv.appendChild(document.createTextNode("Go to..."));
+
+  if(map._search_only) {
+    container.appendChild(SearchDiv);
+      map._search_result_callback = function(map, placemark) {
+	  var point = placemark.Point.coordinates;
+	  map.setCenter(new GLatLng(point[1], point[0]), 8+placemark.AddressDetails.Accuracy);
+      }
+  }
+  else {
+    container.appendChild(EditDiv);
+    map._search_result_callback = _mark_new_location;
+  }
+  var editctl = this;
+  GEvent.addDomListener(EditDiv, "click", function() {
+    if (editctl.editing) {
+        var point = map._jifty_location.getPoint();
+	$(map._jifty_form_x).value = point.lng()
+	$(map._jifty_form_y).value = point.lat()
+	EditDiv.innerHTML = "Edit";
+	container.removeChild(container.lastChild);
+	container.removeChild(container.lastChild);
+	editctl.editing = false;
+    }
+    else {
+	map._jifty_location_orig = map._jifty_location;
+        container.appendChild(CancelDiv);
+        container.appendChild(SearchDiv);
+	EditDiv.innerHTML = "Done";
+	editctl.editing = true;
+    }
+  });
+
+  GEvent.addDomListener(CancelDiv, "click", function() {
+      map.removeOverlay(map._jifty_location);
+      map._jifty_location = map._jifty_location_orig;
+      map.addOverlay(map._jifty_location);
+
+      container.removeChild(container.lastChild);
+      container.removeChild(container.lastChild);
+      EditDiv.innerHTML = "Edit";
+      editctl.editing = false;
+  });
+
+  GEvent.addDomListener(SearchDiv, "click", function() {
+      var element = document.createElement('div');
+      var field= document.createElement('input');
+      field.setAttribute('type', 'text');
+      field.style.width = '150px';
+      // port to yui event
+      field.onkeypress = function(e) {
+	  var event = e || window.event;
+	  if ((event.charCode || event.keyCode) == 13) {
+	      this.nextSibling.onclick();
+	      event.returnValue = false;
+	      return false;
+	  }
+      };
+      element.appendChild(field);
+      var submit= document.createElement('input');
+      submit.id = 'blahblah';
+      submit.value = 'Query';
+      submit.setAttribute('type', 'button');
+      submit.onclick = function() { _handle_search(map, field.value) };
+      element.appendChild(submit);
+      map.openInfoWindow(map.getCenter(), element, { maxWidth: 100 } );
+  });
+
+  map.getContainer().appendChild(container);
+  map._jifty_edit_control = this;
+  this.editing = false;
+  return container;
+}
+
+function _mark_new_location(map, placemark) {
+    var point = placemark.Point.coordinates;
+    if (map._jifty_location)
+	map.removeOverlay(map._jifty_location);
+    map._jifty_location = new GMarker(new GLatLng(point[1], point[0]));
+    map.addOverlay(map._jifty_location);
+    map.closeInfoWindow();
+    map.setCenter(map._jifty_location.getPoint(), 8+placemark.AddressDetails.Accuracy);
+}
+
+function _handle_search(map, address) {
+    var geocoder = new GClientGeocoder();
+    geocoder.getLocations
+      (address,
+       function (result) {
+	   if(result.Placemark) {
+	       if (result.Placemark.length == 1)
+		   map._search_result_callback(map, result.Placemark[0]);
+	       else
+		   _handle_multiple_results(map, result);
+	   }
+	   else {
+	       // TODO: show error in warning box in infowindow rather than alert
+	       alert('address not found');
+	   }
+       });
+}
+
+function _handle_multiple_results(map, result) {
+    var buf = '<a href="#" onclick="_handle_result_click(this.parentNode, null); return false;">Close</a><ul>';
+    for (var i = 0; i < result.Placemark.length; ++i) {
+	var data = result.Placemark[i];
+	buf += '<li><a href="#" onclick='+"'"+
+            '_handle_result_click(this.parentNode.parentNode.parentNode, '+JSON.stringify(data)+'); return false;' +
+          "'>"+data.address+'</a></li>';
+    }
+    buf += '</ul>';
+    map._jifty_search_result.innerHTML = buf;
+    map._jifty_search_result.style.display = "block";
+    map._jifty_search_result._map = map;
+}
+
+function _handle_result_click(e, data) {
+    e.style.display = 'none';
+    var map = e._map; e._map = null; /* circular reference? */
+    if (data)
+	map._search_result_callback(map, data);
+}
+
+EditLocationControl.prototype.getDefaultPosition = function() {
+  return new GControlPosition(G_ANCHOR_BOTTOM_RIGHT, new GSize(7, 7));
+}
+
+EditLocationControl.prototype.setButtonStyle_ = function(button) {
+  button.style.textDecoration = "underline";
+  button.style.color = "#0000cc";
+  button.style.backgroundColor = "white";
+  button.style.font = "small Arial";
+  button.style.fontSize = "0.8em";
+  button.style.border = "1px solid black";
+  button.style.padding = "2px";
+  button.style.marginBottom = "3px";
+  button.style.textAlign = "center";
+  button.style.width = "4em";
+  button.style.cursor = "pointer";
+}
+
+
+}

Modified: jifty/branches/autoversioning/share/po/en.po
==============================================================================
--- jifty/branches/autoversioning/share/po/en.po	(original)
+++ jifty/branches/autoversioning/share/po/en.po	Sun Jul 22 21:13:55 2007
@@ -12,7 +12,7 @@
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
 "MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
 #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmLostPassword.pm:38

Modified: jifty/branches/autoversioning/share/po/zh_cn.po
==============================================================================
--- jifty/branches/autoversioning/share/po/zh_cn.po	(original)
+++ jifty/branches/autoversioning/share/po/zh_cn.po	Sun Jul 22 21:13:55 2007
@@ -27,6 +27,14 @@
 "\n"
 "%2\n"
 msgstr ""
+"\n"
+"您 (或自称是您的某人) 要求重设 %1 的密码.\n"
+"\n"
+"如果您不想重设密码,请忽略这封信\n"
+"\n"
+"若要重设密码,请点击以下链接:\n"
+"\n"
+"%2\n"
 
 #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:41
 #. ($appname,$confirm_url)
@@ -39,6 +47,12 @@
 "\n"
 "%2\n"
 msgstr ""
+"\n"
+"您(或自称是您的某人)在 %1 申请注册.\n"
+"\n"
+"请点击以下链接,以确认你的电子邮箱:\n"
+"\n"
+"%2\n"
 
 #: lib/Jifty/Action/Record/Search.pm:125
 msgid "!=>< allowed"
@@ -47,7 +61,7 @@
 #: lib/Jifty/Notification.pm:94
 #. ($appname, Jifty->config->framework('AdminEmail')
 msgid "%1 <%2>"
-msgstr ""
+msgstr "%1 <%2>"
 
 #: lib/Jifty/Action/Record/Search.pm:115
 #. ($label)
@@ -67,7 +81,7 @@
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:141
 #. ($collection-> count)
 msgid "%1 entries"
-msgstr "%1 条记录"
+msgstr "共 %1 条记录"
 
 #: lib/Jifty/Action/Record/Search.pm:123
 #. ($label)
@@ -126,16 +140,16 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:58
 msgid ". Your email address has now been confirmed."
-msgstr ""
+msgstr ". 现已成功确认您的电子邮箱."
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:96
 msgid "A link to reset your password has been sent to your email account."
-msgstr ""
+msgstr "重设密码的链接已发送到您的电子邮箱."
 
 #: lib/Jifty/Notification.pm:96
 #. ($appname)
 msgid "A notification from %1!"
-msgstr ""
+msgstr "从 %1 送来的消息!"
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:443
 msgid "Actions"
@@ -143,7 +157,7 @@
 
 #: lib/Jifty/Plugin/SkeletonApp/Dispatcher.pm:28
 msgid "Administration"
-msgstr "管理接口"
+msgstr "管理界面"
 
 #: lib/Jifty/View/Declare/Helpers.pm:363 share/web/templates/_elements/wrapper:11
 msgid "Administration mode is enabled."
@@ -163,7 +177,7 @@
 
 #: lib/Jifty/Plugin/ErrorTemplates/View.pm:131
 msgid "Anyway, the software has logged this error."
-msgstr ""
+msgstr "系统已记录该错误."
 
 #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:19
 msgid "Authentication token"
@@ -179,7 +193,7 @@
 
 #: share/web/templates/__jifty/halo:117
 msgid "Bindings"
-msgstr "快速键"
+msgstr "快捷键"
 
 #: share/web/templates/helpers/calendar.html:4
 #. (_ &><body class="calpopup"><a href="#" onclick="window.close()
@@ -250,15 +264,15 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:23 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:32
 msgid "Email"
-msgstr ""
+msgstr "电子邮箱"
 
 #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:33
 msgid "Email address"
-msgstr ""
+msgstr "电子邮箱"
 
 #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:35
 msgid "Email address confirmed?"
-msgstr ""
+msgstr "已确认电子邮箱?"
 
 #: lib/Jifty/Action.pm:1158
 msgid "Foo cannot contain -, *, +, or ?."
@@ -291,7 +305,7 @@
 #: lib/Jifty/I18N.pm:19 lib/Jifty/I18N.pm:23
 #. ('World')
 msgid "Hello, %1!"
-msgstr ""
+msgstr "%1, 您好!"
 
 #: lib/Jifty/Plugin/SkeletonApp/View.pm:31 share/web/templates/_elements/sidebar:5
 #. ($u->$method()
@@ -304,7 +318,7 @@
 
 #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:30
 msgid "How should I display your name to other users?"
-msgstr ""
+msgstr "您在本系统的名字"
 
 #: lib/Jifty/Action.pm:1090
 msgid "I changed $field for you"
@@ -312,15 +326,15 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:64
 msgid "I'm not sure how this happened."
-msgstr ""
+msgstr "我也不知道怎么回事."
 
 #: lib/Jifty/Plugin/ErrorTemplates/View.pm:62
 msgid "Internal error"
-msgstr ""
+msgstr "内部错误"
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:78 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:79
 msgid "It doesn't look like there's an account by that name."
-msgstr ""
+msgstr "该账号不存在."
 
 #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:89
 msgid "It looks like somebody else is using that address. Is there a chance you have another account?"
@@ -356,23 +370,23 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:106
 msgid "Login"
-msgstr ""
+msgstr "登录"
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:55
 msgid "Login with a password"
-msgstr ""
+msgstr "使用密码登录"
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:40
 msgid "Login!"
-msgstr ""
+msgstr "登录!"
 
 #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:123
 msgid "Logout"
-msgstr ""
+msgstr "注销"
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:63
 msgid "Lost your password?"
-msgstr ""
+msgstr "忘记密码?"
 
 #:
 msgid "Manage %1 records"
@@ -380,12 +394,12 @@
 
 #:
 msgid "Manage records:"
-msgstr "管理记录:"
+msgstr "管理记录:"
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:46 lib/Jifty/Plugin/AdminUI/View-not-yet.pm:473
 #. ($object_type)
 msgid "Manage records: [_1]"
-msgstr ""
+msgstr "管理记录: [_1]"
 
 #: share/web/templates/__jifty/error/mason_internal_error:1
 msgid "Mason error"
@@ -397,7 +411,7 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:81
 msgid "New password"
-msgstr ""
+msgstr "新密码"
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:172
 msgid "Next Page"
@@ -405,11 +419,11 @@
 
 #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:29
 msgid "Nickname"
-msgstr ""
+msgstr "昵称"
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:52
 msgid "No account yet? It's quick and easy. "
-msgstr ""
+msgstr "还没有账号?您可以方便快捷地注册. "
 
 #: lib/Jifty/Action/Record/Search.pm:130
 msgid "No field contains"
@@ -425,11 +439,11 @@
 
 #:
 msgid "Online Documentation"
-msgstr "线上文件"
+msgstr "在线文件"
 
 #: lib/Jifty/Plugin/OnlineDocs/Dispatcher.pm:26
 msgid "Online docs"
-msgstr "线上文件"
+msgstr "在线文件"
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:134
 #. ($page, $collection->pager->last_page)
@@ -442,15 +456,15 @@
 
 #: share/web/templates/__jifty/halo:72
 msgid "Parent"
-msgstr "上层组件"
+msgstr "父组件"
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:29 lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:32 lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:26
 msgid "Password"
-msgstr ""
+msgstr "密码"
 
 #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:88
 msgid "Passwords need to be at least six characters long"
-msgstr ""
+msgstr "密码长度至少为6位"
 
 #: lib/Jifty/Record.pm:272 lib/Jifty/Record.pm:351 lib/Jifty/Record.pm:70
 msgid "Permission denied"
@@ -458,15 +472,15 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:66
 msgid "Please email us!"
-msgstr ""
+msgstr "请发邮件通知我们!"
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:163
 msgid "Previous Page"
-msgstr "上一页"
+msgstr "前一页"
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:65
 msgid "Really, really sorry."
-msgstr ""
+msgstr "非常非常抱歉"
 
 #:
 msgid "Record created"
@@ -474,16 +488,16 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:37
 msgid "Remember me?"
-msgstr ""
+msgstr "记住我?"
 
 #: share/web/templates/__jifty/halo:69
 #. ($frame->{'render_time'})
 msgid "Rendered in %1s"
-msgstr "页面绘制时间: %1 秒"
+msgstr "页面生成时间: %1 秒"
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:78
 msgid "Reset lost password"
-msgstr ""
+msgstr "重设密码"
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:53
 msgid "Run the action"
@@ -491,7 +505,7 @@
 
 #: share/web/templates/__jifty/halo:111
 msgid "SQL Statements"
-msgstr "SQL 陈述式"
+msgstr "SQL 语句"
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:327
 msgid "Save"
@@ -499,7 +513,7 @@
 
 #:
 msgid "Schema"
-msgstr "模式"
+msgstr "纲要"
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:304
 msgid "Search"
@@ -507,27 +521,27 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:119
 msgid "Send"
-msgstr ""
+msgstr "发送"
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:97
 msgid "Send a link to reset your password"
-msgstr ""
+msgstr "发送重设密码的链接"
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:109 lib/Jifty/Plugin/Authentication/Password/View.pm:114
 msgid "Send a password reminder"
-msgstr ""
+msgstr "发送密码提示"
 
 #: lib/Jifty/Plugin/Authentication/Password/Dispatcher.pm:111
 msgid "Sign up"
-msgstr ""
+msgstr "注册"
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:53
 msgid "Sign up for an account!"
-msgstr ""
+msgstr "现在就注册!"
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:30 lib/Jifty/Plugin/Authentication/Password/View.pm:35
 msgid "Signup"
-msgstr ""
+msgstr "注册"
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108
 #. ($msg)
@@ -544,7 +558,7 @@
 
 #: lib/Jifty/Plugin/ErrorTemplates/View.pm:132
 msgid "Sorry about this."
-msgstr ""
+msgstr "非常抱歉"
 
 #:
 msgid "Table of Contents"
@@ -553,7 +567,7 @@
 #: lib/Jifty/Plugin/User/Mixin/Model/User.pm:82
 #. ($new_email)
 msgid "That %1 doesn't look like an email address."
-msgstr ""
+msgstr "%1 不是合法的电子邮箱"
 
 #: lib/Jifty/Action.pm:878
 msgid "That doesn't look like a correct value"
@@ -561,7 +575,7 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:71 lib/Jifty/Plugin/Authentication/Password/Action/SendPasswordReminder.pm:72 lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:70
 msgid "That doesn't look like an email address."
-msgstr ""
+msgstr "这不是合法的电子邮箱."
 
 #: lib/Jifty/Action/Record.pm:249
 msgid "That doesn't look right, but I don't know why"
@@ -569,7 +583,7 @@
 
 #: lib/Jifty/Action/Record.pm:181
 msgid "The passwords you typed didn't match each other"
-msgstr "两组口令不匹配."
+msgstr "两组密码不匹配."
 
 #: lib/Jifty/Web.pm:365
 msgid "There was an error completing the request.  Please try again later."
@@ -577,7 +591,7 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:81
 msgid "There was an error setting your password."
-msgstr ""
+msgstr "设置密码时出现错误."
 
 #: lib/Jifty/Plugin/ErrorTemplates/View.pm:37
 msgid "There's a pretty good chance that error message doesn't mean anything to you, but we'd rather you have a little bit of information about what went wrong than nothing. We've logged this error, so we know we need to write something friendly explaining just what happened and how to fix it."
@@ -585,7 +599,7 @@
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:419
 msgid "This console lets you manage the records in your Jifty database. Below, you should see a list of all your database tables. Feel free to go through and add, delete or modify records."
-msgstr "您可利用此界面来管理数据库的内容. 请点选表格名称, 进行增删及编辑."
+msgstr "您可利用此界面来管理数据库的内容. 请选择表格名称, 进行增删及编辑."
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:425
 msgid "To disable this administrative console, add \"AdminMode: 0\" under the \"framework:\" settings in the config file (etc/config.yml)."
@@ -593,19 +607,19 @@
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:127
 msgid "Toggle search"
-msgstr "切换搜寻画面"
+msgstr "切换搜索页面"
 
 #: lib/Jifty/Plugin/ErrorTemplates/View.pm:173 share/web/templates/__jifty/error/mason_internal_error:6
 msgid "Try again"
-msgstr "重试一下"
+msgstr "重试"
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:108
 msgid "Try again later. We're really, really sorry."
-msgstr ""
+msgstr "请稍后再试,抱歉."
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:53
 msgid "Type that again?"
-msgstr ""
+msgstr "请再输入一次"
 
 #: lib/Jifty/Action/Record/Update.pm:156
 msgid "Updated"
@@ -613,7 +627,7 @@
 
 #: share/web/templates/__jifty/halo:93
 msgid "Variables"
-msgstr "变項"
+msgstr "变项"
 
 #: lib/Jifty.pm:27
 msgid "W00t"
@@ -621,52 +635,52 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:114
 msgid "We've sent a confirmation message to your email box."
-msgstr ""
+msgstr "系统已将确认信发送到您的电子邮箱."
 
 #: lib/Jifty/I18N.pm:31
 #. ('Bob', 'World')
 msgid "Welcome %1 to the %2"
-msgstr ""
+msgstr "%2, 欢迎来到 %1"
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:181
 #. ($user->name)
 msgid "Welcome back, %1."
-msgstr ""
+msgstr "欢迎回来, %1."
 
 #: lib/Jifty/Plugin/Authentication/Password/Notification/ConfirmEmail.pm:40
 #. ($appname)
 msgid "Welcome to %1!"
-msgstr ""
+msgstr "欢迎来到 %1!"
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Signup.pm:113
 #. (Jifty->config->framework('ApplicationName')
 msgid "Welcome to %1, %2."
-msgstr ""
+msgstr "%2, 欢迎来到 %1"
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:57
 #. (Jifty->config->framework('ApplicationName')
 msgid "Welcome to %1, %2. "
-msgstr ""
+msgstr "%2, 欢迎来到 %1"
 
 #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:1
 msgid "Welcome to your new Jifty application"
-msgstr "欢迎光临您的崭新的 Jifty 应用程序"
+msgstr "欢迎光临您崭新的 Jifty 应用程序"
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:63
 msgid "You don't exist."
-msgstr ""
+msgstr "该帐号不存在."
 
 #: lib/Jifty/Plugin/ErrorTemplates/View.pm:130
 msgid "You got to a page that we don't think exists."
-msgstr ""
+msgstr "此页面不存在."
 
 #: share/web/templates/dhandler:5
 msgid "You got to a page that we don't think exists.  Anyway, the software has logged this error. Sorry about this."
-msgstr "抱歉, 此页面不存在, 系统已留下纪录."
+msgstr "抱歉, 此页面不存在, 系统已记录该错误."
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/ConfirmEmail.pm:44
 msgid "You have already confirmed your account."
-msgstr ""
+msgstr "您已经确认过该账号了."
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:98
 msgid "You lost your password. A link to reset it will be sent to the following email address:"
@@ -678,11 +692,11 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:152
 msgid "You may have mistyped your email address or password. Give it another shot."
-msgstr ""
+msgstr "您或许输错了电子邮箱或密码,请重试."
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:146
 msgid "You may have mistyped your email or password. Give it another shot."
-msgstr ""
+msgstr "您或许输错了电子邮箱或密码,请重试."
 
 #: lib/Jifty/Action.pm:865
 msgid "You need to fill in this field"
@@ -691,11 +705,11 @@
 #: lib/Jifty/Plugin/SkeletonApp/View.pm:75 share/web/templates/index.html:3
 #. ('http://hdl.loc.gov/loc.pnp/cph.3c13461')
 msgid "You said you wanted a pony. (Source %1)"
-msgstr "您可不正是想要一匹小马吗? (参见 %1)"
+msgstr "您不正想要一匹小马吗? (参见 %1)"
 
 #: lib/Jifty/Plugin/Authentication/Password/View.pm:69
 msgid "You're already logged in."
-msgstr ""
+msgstr "您已经登录了."
 
 #: lib/Jifty/Plugin/SkeletonApp/View.pm:34 share/web/templates/_elements/sidebar:7
 msgid "You're not currently signed in."
@@ -703,15 +717,15 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/Login.pm:38
 msgid "Your browser can remember your login for you"
-msgstr ""
+msgstr "下次开启浏览器时, 是否保持登录状态?"
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:87
 msgid "Your password has been reset.  Welcome back."
-msgstr ""
+msgstr "您的密码已被重设. 欢迎回来."
 
 #: lib/Jifty/Plugin/Authentication/Password/Mixin/Model/User.pm:28
 msgid "Your password should be at least six characters"
-msgstr ""
+msgstr "密码长度至少为6位"
 
 #: lib/Jifty/Plugin/AdminUI/View-not-yet.pm:246
 msgid "asc"
@@ -723,7 +737,7 @@
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/SendAccountConfirmation.pm:31
 msgid "email address"
-msgstr ""
+msgstr "电子邮箱"
 
 #: lib/Jifty/Plugin/ErrorTemplates/View.pm:46
 msgid "for now, and try to forget that we let you down."
@@ -731,16 +745,16 @@
 
 #: lib/Jifty/Manual/PageRegions.pod:188
 msgid "text of the link"
-msgstr "连结文字"
+msgstr "链接文字"
 
 #: lib/Jifty/Manual/PageRegions.pod:225
 msgid "text of the link that hides"
-msgstr "隐藏连结文字"
+msgstr "隐藏链接文字"
 
 #: lib/Jifty/Plugin/Authentication/Password/Action/ResetLostPassword.pm:37
 msgid "type your password again"
-msgstr ""
+msgstr "重新输入密码"
 
 #: lib/Jifty/Action.pm:1050
 msgid "warning"
-msgstr ""
+msgstr "警告"

Modified: jifty/branches/autoversioning/share/web/static/js/jifty.js
==============================================================================
--- jifty/branches/autoversioning/share/web/static/js/jifty.js	(original)
+++ jifty/branches/autoversioning/share/web/static/js/jifty.js	Sun Jul 22 21:13:55 2007
@@ -121,7 +121,11 @@
                     a['fields'][Form.Element.getField(f)] = {};
                 var field = Form.Element.getField(f);
                 var type = Form.Element.getType(f);
-                    
+
+                // XXX: fallback value being an array makes server
+                // upset, we don't think that should happen anyway
+                if (type == 'fallback' && a['fields'][field][type])
+                    continue                    
                 a['fields'][field][type] = this._mergeValues(a['fields'][field][type],
                                                              Form.Element.getValue(f));
             }
@@ -686,9 +690,12 @@
 	    } else {
 		Element.update(element, textContent.stripScripts());
 	    }
-	    // We need to give the browser some "settle" time before we eval scripts in the body
-	    setTimeout((function() { this.evalScripts() }).bind(textContent), 10);
-	    Behaviour.apply(element);
+	    // We need to give the browser some "settle" time before
+	    // we eval scripts in the body
+        YAHOO.util.Event.onAvailable(element.id, function() {
+            (function() { this.evalScripts() }).bind(textContent)();
+        });
+        Behaviour.apply(element);
 	}
     }
     dom_fragment.setArgs(new_dom_args);
@@ -719,7 +726,6 @@
 //     - 'mode' is one of 'Replace', or the name of a Prototype Insertion
 //     - 'effect' is the name of a Prototype Effect
 function update() {
-    // If we don't have XMLHttpRequest, bail and fallback on full-page
     // loads
     if(!Ajax.getTransport()) return true;
     // XXX: prevent default behavior in IE
@@ -740,11 +746,29 @@
     // Grab extra arguments (from a button)
     var button_args = Form.Element.buttonFormElements(trigger);
 
+    var form = Form.Element.getForm(trigger);
+    // If the action is null, take all actions
+    if (named_args['actions'] == null) {
+        named_args['actions'] = {};
+        // default to disable fields
+        if (form)
+            Form.getActions(form).map(function(x){
+                named_args['actions'][x.moniker] = 1;
+            });
+    }
+    var optional_fragments;
+    if (form && form['J:CALL']) 
+	optional_fragments = [ prepare_element_for_update({'mode':'Replace','args':{},'region':'__page','path': null}) ];
     // Build actions structure
     request['actions'] = $H();
     for (var moniker in named_args['actions']) {
         var disable = named_args['actions'][moniker];
         var a = new Action(moniker, button_args);
+        // Special case for Redirect, allow optional, implicit __page
+        // from the response to be used.
+        if (a.actionClass == 'Jifty::Action::Redirect')
+            optional_fragments = [ prepare_element_for_update({'mode':'Replace','args':{},'region':'__page','path': a.fields().last().value}) ];
+
         if (a.register) {
             if (a.hasUpload())
                 return true;
@@ -778,13 +802,14 @@
         // Grab the XML response
         var response = transport.responseXML.documentElement;
         // Loop through the result looking for it
+        var expected_fragments = optional_fragments ? optional_fragments : named_args['fragments'];
         for (var response_fragment = response.firstChild;
              response_fragment != null && response_fragment.nodeName == 'fragment';
              response_fragment = response_fragment.nextSibling) {
 
             var f; 
-            for (var i = 0; i < named_args['fragments'].length; i++) {
-                f = named_args['fragments'][i];
+            for (var i = 0; i < expected_fragments.length; i++) {
+                f = expected_fragments[i];
                 if (response_fragment.getAttribute("id") == f['region'])
                     break;
             }
@@ -806,6 +831,13 @@
                 }
             }
         }
+        for (var redirect = response.firstChild;
+             redirect != null;
+             redirect = redirect.nextSibling) {
+            if (redirect.nodeName == 'redirect') {
+                document.location =  redirect.firstChild.firstChild.nodeValue;
+            }
+        }
     };
     var onFailure = function(transport, object) {
         hide_wait_message_now();
@@ -829,6 +861,9 @@
         request['variables']['region-'+k] = current_args[k];
     }
 
+    // Build continuation structure
+    request['continuation'] = named_args['continuation'];
+
     // Push any state variables which we set into the forms
     for (var i = 0; i < document.forms.length; i++) {
         var form = document.forms[i];

Modified: jifty/branches/autoversioning/share/web/static/js/key_bindings.js
==============================================================================
--- jifty/branches/autoversioning/share/web/static/js/key_bindings.js	(original)
+++ jifty/branches/autoversioning/share/web/static/js/key_bindings.js	Sun Jul 22 21:13:55 2007
@@ -24,6 +24,10 @@
         DOM.Events.removeListener(Jifty.KeyBindings.listener);
     },
 
+    reset: function() {
+        Jifty.KeyBindings.bindings = new Array();
+    },
+
     doClick: function(e) {
         if (e.target.nodeType == 3) // defeat Safari bug
             e.target = e.target.parentNode;

Modified: jifty/branches/autoversioning/share/web/static/js/yui/calendar.js
==============================================================================
--- jifty/branches/autoversioning/share/web/static/js/yui/calendar.js	(original)
+++ jifty/branches/autoversioning/share/web/static/js/yui/calendar.js	Sun Jul 22 21:13:55 2007
@@ -1,4 +1,8 @@
 /*
+    This file has been PATCHED by trs to allow selecting of out of month dates.
+    Please do not update it without also applying the patch (oom_select.patch).
+*/
+/*
 Copyright (c) 2007, Yahoo! Inc. All rights reserved.
 Code licensed under the BSD License:
 http://developer.yahoo.net/yui/license.txt
@@ -903,6 +907,7 @@
 	MINDATE : {key:"mindate", value:null},
 	MAXDATE : {key:"maxdate", value:null},
 	MULTI_SELECT : {key:"multi_select",	value:false},
+	OOM_SELECT : {key:"oom_select",	value:false},
 	START_WEEKDAY : {key:"start_weekday", value:0},
 	SHOW_WEEKDAYS : {key:"show_weekdays", value:true},
 	SHOW_WEEK_HEADER : {key:"show_week_header", value:false},
@@ -1505,6 +1510,14 @@
 	*/
 	this.cfg.addProperty(defCfg.MULTI_SELECT.key,	{ value:defCfg.MULTI_SELECT.value, handler:this.configOptions, validator:this.cfg.checkBoolean } );
 
+    /**
+    * True if the Calendar should allow selection of out-of-month dates. False by default.
+    * @config OOM_SELECT
+    * @type Boolean
+    * @default false
+    */
+    this.cfg.addProperty(defCfg.OOM_SELECT.key,      { value:defCfg.OOM_SELECT.value, handler:this.configOptions, validator:this.cfg.checkBoolean } );
+
 	/**
 	* The weekday the week begins on. Default is 0 (Sunday).
 	* @config START_WEEKDAY
@@ -2176,7 +2189,7 @@
 		weekClass = weekPrefix + weekNum;
 
 		// Local OOM check for performance, since we already have pagedate
-		if (r !== 0 && hideBlankWeeks === true && workingDate.getMonth() != useDate.getMonth()) {
+		if (r !== 0 && hideBlankWeeks === true && workingDate.getMonth() != useDate.getMonth() && !this.cfg.getProperty(defCfg.OOM_SELECT.key)) {
 			break;
 		} else {
 
@@ -2203,7 +2216,7 @@
 				this.cellDates[this.cellDates.length] = workingArray; // Add this date to cellDates
 				
 				// Local OOM check for performance, since we already have pagedate
-				if (workingDate.getMonth() != useDate.getMonth()) {
+				if (workingDate.getMonth() != useDate.getMonth() && !this.cfg.getProperty(defCfg.OOM_SELECT.key)) {
 					cellRenderers[cellRenderers.length]=cal.renderCellNotThisMonth;
 				} else {
 					YAHOO.util.Dom.addClass(cell, workingDayPrefix + workingDate.getDay());

Added: jifty/branches/autoversioning/share/web/static/js/yui/oom_select.patch
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/share/web/static/js/yui/oom_select.patch	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,54 @@
+=== share/web/static/js/yui/calendar.js
+==================================================================
+--- share/web/static/js/yui/calendar.js	(revision 24788)
++++ share/web/static/js/yui/calendar.js	(local)
+@@ -1,4 +1,8 @@
+ /*
++    This file has been PATCHED by trs to allow selecting of out of month dates.
++    Please do not update it without also applying the patch (oom_select.patch).
++*/
++/*
+ Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+ Code licensed under the BSD License:
+ http://developer.yahoo.net/yui/license.txt
+@@ -903,6 +907,7 @@
+ 	MINDATE : {key:"mindate", value:null},
+ 	MAXDATE : {key:"maxdate", value:null},
+ 	MULTI_SELECT : {key:"multi_select",	value:false},
++	OOM_SELECT : {key:"oom_select",	value:false},
+ 	START_WEEKDAY : {key:"start_weekday", value:0},
+ 	SHOW_WEEKDAYS : {key:"show_weekdays", value:true},
+ 	SHOW_WEEK_HEADER : {key:"show_week_header", value:false},
+@@ -1505,6 +1510,14 @@
+ 	*/
+ 	this.cfg.addProperty(defCfg.MULTI_SELECT.key,	{ value:defCfg.MULTI_SELECT.value, handler:this.configOptions, validator:this.cfg.checkBoolean } );
+ 
++    /**
++    * True if the Calendar should allow selection of out-of-month dates. False by default.
++    * @config OOM_SELECT
++    * @type Boolean
++    * @default false
++    */
++    this.cfg.addProperty(defCfg.OOM_SELECT.key,      { value:defCfg.OOM_SELECT.value, handler:this.configOptions, validator:this.cfg.checkBoolean } );
++
+ 	/**
+ 	* The weekday the week begins on. Default is 0 (Sunday).
+ 	* @config START_WEEKDAY
+@@ -2176,7 +2189,7 @@
+ 		weekClass = weekPrefix + weekNum;
+ 
+ 		// Local OOM check for performance, since we already have pagedate
+-		if (r !== 0 && hideBlankWeeks === true && workingDate.getMonth() != useDate.getMonth()) {
++		if (r !== 0 && hideBlankWeeks === true && workingDate.getMonth() != useDate.getMonth() && !this.cfg.getProperty(defCfg.OOM_SELECT.key)) {
+ 			break;
+ 		} else {
+ 
+@@ -2203,7 +2216,7 @@
+ 				this.cellDates[this.cellDates.length] = workingArray; // Add this date to cellDates
+ 				
+ 				// Local OOM check for performance, since we already have pagedate
+-				if (workingDate.getMonth() != useDate.getMonth()) {
++				if (workingDate.getMonth() != useDate.getMonth() && !this.cfg.getProperty(defCfg.OOM_SELECT.key)) {
+ 					cellRenderers[cellRenderers.length]=cal.renderCellNotThisMonth;
+ 				} else {
+ 					YAHOO.util.Dom.addClass(cell, workingDayPrefix + workingDate.getDay());

Modified: jifty/branches/autoversioning/share/web/templates/__jifty/webservices/xml
==============================================================================
--- jifty/branches/autoversioning/share/web/templates/__jifty/webservices/xml	(original)
+++ jifty/branches/autoversioning/share/web/templates/__jifty/webservices/xml	Sun Jul 22 21:13:55 2007
@@ -4,6 +4,14 @@
 $writer->xmlDecl( "UTF-8", "yes" );
 $writer->startTag("response");
 
+if (my $ext = Jifty->web->request->argument('_webservice_external_redirect')) {
+    $writer->startTag("redirect");
+    $writer->cdataElement(url=> $ext);
+
+    $writer->endTag();
+}
+else {
+
 FRAGMENT:
 for my $f ( Jifty->web->request->fragments ) {
     # Set up the region stack
@@ -27,7 +35,7 @@
 
         $new ||= Jifty::Web::PageRegion->new(
             name           => $f->name,
-            path           => $f->path,
+            path           => URI::Escape::uri_unescape($f->path),
             region_wrapper => $f->wrapper,
             parent         => Jifty->web->current_region,
             defaults       => \%defaults,
@@ -50,6 +58,8 @@
     Jifty->web->current_region->exit while Jifty->web->current_region;
 }
 
+}
+
 my %results = Jifty->web->response->results;
 for (keys %results) {
     $writer->startTag("result", moniker => $_, class => $results{$_}->action_class);

Modified: jifty/branches/autoversioning/share/web/templates/_elements/sidebar
==============================================================================
--- jifty/branches/autoversioning/share/web/templates/_elements/sidebar	(original)
+++ jifty/branches/autoversioning/share/web/templates/_elements/sidebar	Sun Jul 22 21:13:55 2007
@@ -1,8 +1,7 @@
 <div id="salutation">
-% if (Jifty->web->current_user->id and Jifty->web->current_user->user_object) {
-% my $u = Jifty->web->current_user->user_object;
-% my $method = $u->_brief_description;
-<%_('Hiya, %1.',$u->$method())%>
+% my $u = Jifty->web->current_user;
+% if ($u->id and $u->user_object) {
+<%_('Hiya, %1.',$u->username)%>
 % }  else {
 <%_("You're not currently signed in.")%>
 % }

Modified: jifty/branches/autoversioning/t/Mapper/lib/Mapper/Action/CrossBridge.pm
==============================================================================
--- jifty/branches/autoversioning/t/Mapper/lib/Mapper/Action/CrossBridge.pm	(original)
+++ jifty/branches/autoversioning/t/Mapper/lib/Mapper/Action/CrossBridge.pm	Sun Jul 22 21:13:55 2007
@@ -6,6 +6,7 @@
 param name      => default is 'something';
 param 'quest';
 param colour    => valid are ("Blue, I mean greeeeeen!", "Green");
+param 'castle';
 
 };
 

Modified: jifty/branches/autoversioning/t/Mapper/share/web/templates/index.html
==============================================================================
--- jifty/branches/autoversioning/t/Mapper/share/web/templates/index.html	(original)
+++ jifty/branches/autoversioning/t/Mapper/share/web/templates/index.html	Sun Jul 22 21:13:55 2007
@@ -11,6 +11,7 @@
 % my $grail_1  = Jifty->web->form->add_action( class => 'GetGrail', order => 1 );
 % my $bridge_1 = Jifty->web->new_action( class => 'CrossBridge',    order => 2 );
 <% $bridge_1->form_field( 'quest',  default_value => { result_of => $grail_1, name => 'castle' } ) %>
+<% $bridge_1->form_field( 'castle', default_value => { result_of => $grail_1 } ) %>
 <% $bridge_1->form_field( 'colour', default_value => 'Green' ) %>
 <% Jifty->web->form->submit( label => 'Do both') %>
 <% Jifty->web->form->end %>

Modified: jifty/branches/autoversioning/t/Mapper/t/02-api.t
==============================================================================
--- jifty/branches/autoversioning/t/Mapper/t/02-api.t	(original)
+++ jifty/branches/autoversioning/t/Mapper/t/02-api.t	Sun Jul 22 21:13:55 2007
@@ -12,7 +12,7 @@
 use lib 't/lib';
 use Jifty::SubTest;
 
-use Jifty::Test tests => 11;
+use Jifty::Test tests => 13;
 
 use_ok('Jifty::Test::WWW::Mechanize');
 
@@ -38,6 +38,11 @@
 $mech->content_like(qr/got the grail/i, "Got the grail");
 $mech->content_like(qr/crossed the bridge/i, "And crossed the bridge");
 
+# Tests for proper generation of default "name" parameter to
+# argument_of and result_to
+$mech->content_unlike(qr/R`[^']+`J:A:F/, "Doesn't have full argument name");
+$mech->content_like(qr/J:A:F-castle-(\S+): Aaaaaargh/, "Has the right value name");
+
 # And then, the same, but via default_values on the form field
 $mech->form_number(3);
 ok($mech->click_button(value => "Do both"));

Added: jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/Makefile.PL
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/Makefile.PL	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,7 @@
+use inc::Module::Install;
+
+name        'TestApp::Plugin::AppPluginHasModels';
+version     '0.01';
+requires    'Jifty' => '0.70129';
+
+WriteAll;

Added: jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/bin/jifty
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/bin/jifty	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,11 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+use File::Basename qw(dirname); 
+use UNIVERSAL::require;
+
+use Jifty;
+use Jifty::Script;
+
+local $SIG{INT} = sub { warn "Stopped\n"; exit; };
+Jifty::Script->dispatch();

Added: jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/etc/config.yml
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/etc/config.yml	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,54 @@
+--- 
+framework: 
+  AdminMode: 1
+  ApplicationClass: TestApp::Plugin::AppPluginHasModels
+  ApplicationName: TestApp-Plugin-AppPluginHasModels
+  ApplicationUUID: 646FD662-32DD-11DC-AD79-2A0157C3B83B
+  ConfigFileVersion: 2
+  Database: 
+    CheckSchema: 1
+    Database: testapp_plugin_apppluginhasmodels
+    Driver: SQLite
+    Host: localhost
+    Password: ''
+    RecordBaseClass: Jifty::DBI::Record::Cachable
+    RecordUUIDs: active
+    User: ''
+    Version: 0.0.1
+  DevelMode: 1
+  L10N: 
+    PoDir: share/po
+  LogLevel: INFO
+  Mailer: Sendmail
+  MailerArgs: []
+
+  Plugins: 
+    - LetMe: {}
+    - SkeletonApp: {}
+    - REST: {}
+    - Halo: {}
+    - ErrorTemplates: {}
+    - OnlineDocs: {}
+    - CompressedCSSandJS: {}
+    - AdminUI: {}
+    - TestApp::Plugin::AppPluginHasModels::Plugin::MyAppPlugin: {}
+
+  PubSub: 
+    Backend: Memcached
+    Enable: ~
+  SkipAccessControl: 0
+  TemplateClass: TestApp::Plugin::AppPluginHasModels::View
+  Web: 
+    BaseURL: http://localhost
+    DataDir: var/mason
+    Globals: []
+
+    MasonConfig: 
+      autoflush: 0
+      default_escape_flags: h
+      error_format: text
+      error_mode: fatal
+    Port: 8888
+    ServeStaticFiles: 1
+    StaticRoot: share/web/static
+    TemplateRoot: share/web/templates

Added: jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,7 @@
+use strict;
+use warnings;
+
+package TestApp::Plugin::AppPluginHasModels::Plugin::MyAppPlugin;
+use base qw/ Jifty::Plugin /;
+
+1;

Added: jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model/Color.pm
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model/Color.pm	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,15 @@
+use strict;
+use warnings;
+
+package TestApp::Plugin::AppPluginHasModels::Plugin::MyAppPlugin::Model::Color;
+use Jifty::DBI::Schema;
+
+use TestApp::Plugin::AppPluginHasModels::Plugin::MyAppPlugin::Record schema {
+    column name =>
+        type is 'text';
+
+    column contrasting_color =>
+        type is 'text';
+};
+
+1;

Added: jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/t/plugin-model.t
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp-Plugin-AppPluginHasModels/t/plugin-model.t	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,54 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+=head1 DESCRIPTION
+
+A basic test harness for the Color model.
+
+=cut
+
+use lib 't/lib';
+use Jifty::SubTest;
+use Jifty::Test tests => 12;
+
+# Make sure we can load the model
+use_ok('TestApp::Plugin::AppPluginHasModels::Plugin::MyAppPlugin::Model::Color');
+
+# Grab a system user
+my $system_user = TestApp::Plugin::AppPluginHasModels::CurrentUser->superuser;
+ok($system_user, "Found a system user");
+
+# Try testing a create
+my $o = TestApp::Plugin::AppPluginHasModels::Plugin::MyAppPlugin::Model::Color->new(current_user => $system_user);
+my ($id) = $o->create();
+ok($id, "Color create returned success");
+ok($o->id, "New Color has valid id set");
+is($o->id, $id, "Create returned the right id");
+
+# Does it use a prefixed table
+is($o->table, 'testapp_plugin_apppluginhasmodels_plugin_myappplugin_colors', 'plugin table prefix');
+
+# And another
+$o->create();
+ok($o->id, "Color create returned another value");
+isnt($o->id, $id, "And it is different from the previous one");
+
+# Searches in general
+my $collection = TestApp::Plugin::AppPluginHasModels::Plugin::MyAppPlugin::Model::ColorCollection->new(current_user => $system_user);
+$collection->unlimit;
+is($collection->count, 2, "Finds two records");
+
+# Searches in specific
+$collection->limit(column => 'id', value => $o->id);
+is($collection->count, 1, "Finds one record with specific id");
+
+# Delete one of them
+$o->delete;
+$collection->redo_search;
+is($collection->count, 0, "Deleted row is gone");
+
+# And the other one is still there
+$collection->unlimit;
+is($collection->count, 1, "Still one left");
+

Modified: jifty/branches/autoversioning/t/TestApp/lib/TestApp/Dispatcher.pm
==============================================================================
--- jifty/branches/autoversioning/t/TestApp/lib/TestApp/Dispatcher.pm	(original)
+++ jifty/branches/autoversioning/t/TestApp/lib/TestApp/Dispatcher.pm	Sun Jul 22 21:13:55 2007
@@ -63,4 +63,35 @@
 on '/on_stage_show' => run { show '/index.html'; };
 after '/after_stage_show' => run { show '/index.html'; };
 
+
+
+before 'pre-redir-region' => run {
+    redirect('/post-redir-region');
+
+};
+
+before '__jifty/webservices/*' => run {
+    my (@actions) = grep { $_->class eq 'Jifty::Action::Redirect' } values %{ Jifty->web->request->{'actions'} };
+    $_->active(0) for @actions;
+};
+
+on qr{(__jifty/webservices/.*)} => run {
+    use Data::Dumper;
+    for $act (@actions) {
+	warn Dumper($act);
+    }
+};
+
+on HTTPS '/dispatch/protocol' => run {
+    set content => 'HTTPS';
+};
+
+on HTTP '/dispatch/protocol' => run {
+    set content => 'NOT HTTPS';
+};
+
+on '/dispatch/protocol' => run {
+    set footer => 'normal';
+};
+
 1;

Modified: jifty/branches/autoversioning/t/TestApp/lib/TestApp/View.pm
==============================================================================
--- jifty/branches/autoversioning/t/TestApp/lib/TestApp/View.pm	(original)
+++ jifty/branches/autoversioning/t/TestApp/lib/TestApp/View.pm	Sun Jul 22 21:13:55 2007
@@ -44,8 +44,8 @@
 
 require TestApp::View::base;
 require TestApp::View::instance;
-import_templates TestApp::View::base under '/base';
-import_templates TestApp::View::instance under '/instance';
+alias TestApp::View::base under '/base';
+alias TestApp::View::instance under '/instance';
 
 use Jifty::View::Declare::CRUD;
 
@@ -54,7 +54,7 @@
     if ($model =~ /^.*::(.*?)$/) {
         $bare_model = $1;
     }
-    alias Jifty::View::Declare::CRUD under '/crud/'.$bare_model,  { object_type => $bare_model, base_path => '/crud/'.$bare_model };
+    alias Jifty::View::Declare::CRUD under '/crud/'.$bare_model,  { object_type => $bare_model };
 
 }
 
@@ -65,5 +65,42 @@
     };
 };
 
+template '/foo/list' => sub {
+    outs('list!');
+    show('/foo/item', { id => 1 } );
+    show('/foo/item', { id => 2 } );
+    render_region('special', path => '/foo/item', defaults => { id => 3 } );
+};
+
+template '/foo/item' => sub {
+    my ($self, $args) = @_;
+    span { $args->{id} }
+};
+
+
+template 'region-with-internal-redirect' => page {
+    
+    h1 { 'outer page'};
+
+    render_region('internal', path => '/pre-redir-region');
+    render_region('internal2', path => '/nonredir-region');
+    
+
+    h2 { 'still going'} ;
+};
+
 
+template 'nonredir-region' => sub {
+    h1 { 'other region'};
+};
+
+template 'pre-redir-region' => sub {
+    h1 { 'sorry. no.'};
+};
+
+
+template 'post-redir-region' => sub {
+
+    h1 { 'redirected ok'};
+};
 1;

Modified: jifty/branches/autoversioning/t/TestApp/lib/TestApp/View/base.pm
==============================================================================
--- jifty/branches/autoversioning/t/TestApp/lib/TestApp/View/base.pm	(original)
+++ jifty/branches/autoversioning/t/TestApp/lib/TestApp/View/base.pm	Sun Jul 22 21:13:55 2007
@@ -1,11 +1,13 @@
 package TestApp::View::base;
 use Jifty::View::Declare -base;
 
+sub base_path { '/base' }
+
 template 'list_ht' => sub {
     my $self = shift;
     outs("/base/list=$self");
     for (0..1) {
-	$self->has_template('view')->();
+	$self->resolve_template('view')->();
     }
 };
 
@@ -13,7 +15,7 @@
     my $self = shift;
     outs("/base/list=$self");
     for (0..1) {
-	show('view');
+	show($self->base_path.'/view');
     }
 };
 
@@ -21,7 +23,7 @@
     my $self = shift;
     outs("/base/list=$self");
     for (0..1) {
-	render_region('view-'.$_, path => 'view');
+	render_region('view-'.$_, path => $self->base_path.'/view');
     }
 };
 

Modified: jifty/branches/autoversioning/t/TestApp/lib/TestApp/View/instance.pm
==============================================================================
--- jifty/branches/autoversioning/t/TestApp/lib/TestApp/View/instance.pm	(original)
+++ jifty/branches/autoversioning/t/TestApp/lib/TestApp/View/instance.pm	Sun Jul 22 21:13:55 2007
@@ -2,6 +2,8 @@
 use Jifty::View::Declare -base;
 use base 'TestApp::View::base';
 
+sub base_path { '/instance' }
+
 template 'myview' => sub {
     
 };

Added: jifty/branches/autoversioning/t/TestApp/share/web/templates/dispatch/protocol
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp/share/web/templates/dispatch/protocol	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,3 @@
+<&| /_elements/wrapper, title => "Test of protocol adjectives" &>
+<% Jifty::YAML::Dump(\%ARGS) %>
+</&>

Added: jifty/branches/autoversioning/t/TestApp/t/02-dispatch-http.t
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp/t/02-dispatch-http.t	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,23 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+# Just in case
+BEGIN { delete $ENV{HTTPS}; }
+
+use lib 't/lib';
+use Jifty::SubTest;
+use Jifty::Test tests => 5;
+use Jifty::Test::WWW::Mechanize;
+
+my $server  = Jifty::Test->make_server;
+
+isa_ok($server, 'Jifty::Server');
+
+my $URL     = $server->started_ok;
+my $mech    = Jifty::Test::WWW::Mechanize->new();
+
+$mech->get_ok("$URL/dispatch/protocol", "Got /dispatch/protocol");
+$mech->content_contains("NOT HTTPS");
+$mech->content_contains("normal");
+

Added: jifty/branches/autoversioning/t/TestApp/t/02-dispatch-https.t
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp/t/02-dispatch-https.t	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,24 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+BEGIN { $ENV{HTTPS} = 1; }
+
+use lib 't/lib';
+use Jifty::SubTest;
+use Jifty::Test tests => 6;
+use Jifty::Test::WWW::Mechanize;
+
+my $server  = Jifty::Test->make_server;
+
+isa_ok($server, 'Jifty::Server');
+
+my $URL     = $server->started_ok;
+my $mech    = Jifty::Test::WWW::Mechanize->new();
+
+$mech->get_ok("$URL/dispatch/protocol", "Got /dispatch/protocol");
+$mech->content_contains("HTTPS");
+$mech->content_lacks("NOT");
+$mech->content_contains("normal");
+
+

Modified: jifty/branches/autoversioning/t/TestApp/t/02-dispatch-show-rule-in-wrong-ruleset.t
==============================================================================
--- jifty/branches/autoversioning/t/TestApp/t/02-dispatch-show-rule-in-wrong-ruleset.t	(original)
+++ jifty/branches/autoversioning/t/TestApp/t/02-dispatch-show-rule-in-wrong-ruleset.t	Sun Jul 22 21:13:55 2007
@@ -4,8 +4,9 @@
 
 use lib 't/lib';
 use Jifty::SubTest;
-use Jifty::Test tests => 8;
+use Jifty::Test tests => 9;
 use Jifty::Test::WWW::Mechanize;
+use Test::Log4perl;
 
 my $server  = Jifty::Test->make_server;
 
@@ -14,11 +15,14 @@
 my $URL     = $server->started_ok;
 my $mech    = Jifty::Test::WWW::Mechanize->new();
 
+{
+    my $log = Test::Log4perl->expect(['', warn => qr/You can't call a 'show' rule in a 'before' or 'after' block in the dispatcher/ ]);
 $mech->get("$URL/before_stage_show", "Got /before_stage_show");
 $mech->content_lacks("This is content");
 is( $mech->status , '404');
-
+}
 $mech->get_ok("$URL/on_stage_show", "Got /on_stage_show");
+#diag $mech->content;
 $mech->content_contains("his is content");
 
 $mech->get("$URL/after_stage_show", "Got /after_stage_show");

Modified: jifty/branches/autoversioning/t/TestApp/t/08-notifications.t
==============================================================================
--- jifty/branches/autoversioning/t/TestApp/t/08-notifications.t	(original)
+++ jifty/branches/autoversioning/t/TestApp/t/08-notifications.t	Sun Jul 22 21:13:55 2007
@@ -5,9 +5,29 @@
 use lib 't/lib';
 use Jifty::SubTest;
 
-use Jifty::Test tests => 2;
+use Jifty::Test tests => 4;
+
 use_ok('Jifty::Notification');
+use_ok('Email::MIME::CreateHTML');
+use_ok('Email::MIME');
+use_ok('Email::Send');
+
+my $html = "<html><body>This is the HTML portion of the test email</body></html>";
+
+my $text = "This is the text portion of the text email";
+
+my $test_email = Email::MIME->create_html(
+					  header => [
+						     From => 'test at test',
+						     To => 'test2 at test2',
+						     Subject => 'This is a test email',
+						     ],
+					  body => $html,
+					  text_body => $text
+					  );
+
+
 
-TODO: {local $TODO = "Actually write tests"; ok(0, "Test notifications")};
+# TODO: {local $TODO = "Actually write tests"; ok(0, "Test notifications")};
 
 1;

Modified: jifty/branches/autoversioning/t/TestApp/t/15-template-subclass.t
==============================================================================
--- jifty/branches/autoversioning/t/TestApp/t/15-template-subclass.t	(original)
+++ jifty/branches/autoversioning/t/TestApp/t/15-template-subclass.t	Sun Jul 22 21:13:55 2007
@@ -72,14 +72,8 @@
 my $mech = Jifty::Test::WWW::Mechanize->new;
 foreach my $test (@tests) {
     $mech->get_ok( $URL . $test->{url}, "get '$URL: /jifty/jifty/trunk/t/TestApp/t/15-template-subclass.t $test->{url}'" );
-    TODO: { 
-
-    local $TODO = " Template subclassing needs some love";
-    ok($mech->content =~ qr{$test->{text}}, "found the test content");
-    # $mech->content_contains breaks on multiline content
-    #$mech->content_contains( $test->{text}, "found content '$test->{text}'" );
-    };
 
+    $mech->content_contains( $test->{text}, "found content '$test->{text}'" );
 }
 
 1;

Added: jifty/branches/autoversioning/t/TestApp/t/16-template-region.t
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp/t/16-template-region.t	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,41 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+use lib 't/lib';
+use Jifty::SubTest;
+
+use Jifty::Test;
+use Jifty::Test::WWW::Mechanize;
+
+my @tests = (
+    {   url  => "/foo/list",
+        text => q|list!
+<span>1</span>
+<span>2</span><script type="text/javascript">
+new Region('special',{'id':3},'/foo/item',null);
+</script><div id="region-special">
+<span>3</span></div>|
+    },
+
+);
+
+plan tests => 2 + scalar(@tests) * 2;
+
+my $server = Jifty::Test->make_server;
+isa_ok( $server, 'Jifty::Server' );
+my $URL = $server->started_ok;
+
+use Test::LongString;
+
+my $mech = Jifty::Test::WWW::Mechanize->new;
+foreach my $test (@tests) {
+    $mech->get_ok(
+        $URL . $test->{url},
+        "get '$URL: /jifty/jifty/trunk/t/TestApp/t/15-template-subclass.t $test->{url}'"
+    );
+    is_string( $mech->content, $test->{text}, "found the test content" );
+
+}
+
+1;

Added: jifty/branches/autoversioning/t/TestApp/t/17-template-region-internal-redirect.t
==============================================================================
--- (empty file)
+++ jifty/branches/autoversioning/t/TestApp/t/17-template-region-internal-redirect.t	Sun Jul 22 21:13:55 2007
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+use lib 't/lib';
+use Jifty::SubTest;
+
+use Jifty::Test;
+use Jifty::Test::WWW::Mechanize;
+
+plan tests => 7;
+
+
+my $server = Jifty::Test->make_server;
+isa_ok( $server, 'Jifty::Server' );
+my $URL = $server->started_ok;
+
+
+my $mech = Jifty::Test::WWW::Mechanize->new;
+
+$mech->get_ok( $URL."/region-with-internal-redirect");
+$mech->content_like(qr'redirected ok');
+$mech->content_like(qr'other region');
+$mech->content_like(qr'still going');
+$mech->content_unlike(qr'sorry');
+
+
+1;


More information about the Jifty-commit mailing list