packages feed

hledger-web 0.22.8 → 0.23

raw patch · 8 files changed

+201/−167 lines, 8 filesdep ~hledgerdep ~hledger-libPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: hledger, hledger-lib

API changes (from Hackage documentation)

+ Settings: extraStaticRoot :: Extra -> Maybe Text
- Settings: Extra :: Text -> Maybe Text -> Extra
+ Settings: Extra :: Text -> Maybe Text -> Maybe Text -> Extra
- Settings: staticRoot :: AppConfig DefaultEnv x -> Text
+ Settings: staticRoot :: AppConfig DefaultEnv Extra -> Text

Files

CHANGES view
@@ -1,3 +1,11 @@+See also the hledger changelog.++0.23 (2014/5/1)++- The --static-root flag has been renamed to --file-url.+- hledger-web now builds with Cabal's default -O, not -O2,+  so may be a little quicker/less memory-hungry to install.+   0.22.8 (2014/4/29)  - allow shakespeare 2.* (#179)@@ -33,4 +41,4 @@  0.22.1 (2014/1/6) and older -See http://hledger.org/release-notes or doc/CHANGES.md.+See http://hledger.org/release-notes or doc/RELNOTES.md.
Foundation.hs view
@@ -19,7 +19,7 @@ -- import qualified Settings import Settings.Development (development) import Settings.StaticFiles-import Settings (widgetFile, Extra (..))+import Settings (staticRoot, widgetFile, Extra (..)) #ifndef DEVELOPMENT import Settings (staticDir) import Text.Jasmine (minifym)@@ -117,11 +117,11 @@          hamletToRepHtml $(hamletFile "templates/default-layout-wrapper.hamlet") -    -- -- This is done to provide an optimization for serving static files from-    -- -- a separate domain. Please see the staticRoot setting in Settings.hs-    -- urlRenderOverride y (StaticR s) =-    --     Just $ uncurry (joinPath y (Settings.staticRoot $ settings y)) $ renderRoute s-    -- urlRenderOverride _ _ = Nothing+    -- This is done to provide an optimization for serving static files from+    -- a separate domain. Please see the staticRoot setting in Settings.hs+    urlRenderOverride y (StaticR s) =+        Just $ uncurry (joinPath y (Settings.staticRoot $ settings y)) $ renderRoute s+    urlRenderOverride _ _ = Nothing  #ifndef DEVELOPMENT     -- This function creates static content files in the static folder
Handler/Common.hs view
@@ -330,7 +330,7 @@    allaccts = isNothing inacctmatcher    items = items' -- maybe items' (\m -> filter (matchesAccount m . \(a,_,_,_)->a) items') showacctmatcher    itemAsHtml :: ViewData -> BalanceReportItem -> HtmlUrl AppRoute-   itemAsHtml _ (acct, adisplay, aindent, abal) = [hamlet|+   itemAsHtml _ ((acct, adisplay, aindent), abal) = [hamlet| <tr.item.#{inacctclass}>  <td.account.#{depthclass}>   \#{indent}
Hledger/Web/Main.hs view
@@ -21,6 +21,7 @@ import Network.Wai.Handler.Launch (runUrlPort) -- import Prelude hiding (putStrLn)+import Control.Applicative ((<$>)) import Control.Monad (when) import Data.Text (pack) import System.Exit (exitSuccess)@@ -60,12 +61,13 @@   let j' = filterJournalTransactions (queryFromOpts d $ reportopts_ $ cliopts_ opts) j       p = port_ opts       u = base_url_ opts+      staticRoot = pack <$> static_root_ opts   _ <- printf "Starting web app on port %d with base url %s\n" p u   app <- makeApplication opts j' AppConfig{appEnv = Development                                           ,appPort = p                                           ,appRoot = pack u                                           ,appHost = fromString "*4"-                                          ,appExtra = Extra "" Nothing+                                          ,appExtra = Extra "" Nothing staticRoot                                           }   if server_ opts    then do
Hledger/Web/Options.hs view
@@ -1,6 +1,7 @@ module Hledger.Web.Options where import Prelude+import Control.Applicative ((<$>)) import Data.Maybe import System.Console.CmdArgs import System.Console.CmdArgs.Explicit@@ -23,9 +24,10 @@  webflags :: [Flag [([Char], [Char])]] webflags = [-  flagNone ["server"]  (setboolopt "server") ("log requests, don't auto-exit")- ,flagReq ["base-url"]  (\s opts -> Right $ setopt "base-url" s opts) "URL" ("set the base url (default: "++defbaseurlexample++")")- ,flagReq ["port"]  (\s opts -> Right $ setopt "port" s opts) "PORT" ("listen on this tcp port (default: "++show defport++")")+  flagNone ["server"]   (setboolopt "server") ("log requests, and don't browse or auto-exit")+ ,flagReq  ["port"]     (\s opts -> Right $ setopt "port" s opts) "PORT" ("set the tcp port (default: "++show defport++")")+ ,flagReq  ["base-url"] (\s opts -> Right $ setopt "base-url" s opts) "BASEURL" ("set the base url (default: "++defbaseurlexample++")")+ ,flagReq  ["file-url"] (\s opts -> Right $ setopt "file-url" s opts) "FILEURL" ("set the static files url (default: BASEURL/static)")  ]   webmode :: Mode [([Char], [Char])]@@ -47,6 +49,7 @@      server_   :: Bool     ,base_url_ :: String     ,port_     :: Int+    ,static_root_ :: Maybe String     ,cliopts_  :: CliOpts  } deriving (Show) @@ -56,6 +59,7 @@     def     def     def+    def  -- instance Default WebOpts where def = defwebopts @@ -67,6 +71,7 @@               port_ = p              ,server_ = boolopt "server" rawopts              ,base_url_ = maybe (defbaseurl p) stripTrailingSlash $ maybestringopt "base-url" rawopts+             ,static_root_ = stripTrailingSlash <$> maybestringopt "static-root" rawopts              ,cliopts_   = cliopts              }   where
Settings.hs view
@@ -54,8 +54,10 @@ -- have to make a corresponding change here. -- -- To see how this value is used, see urlRenderOverride in Foundation.hs-staticRoot :: AppConfig DefaultEnv x -> Text-staticRoot conf = [st|#{appRoot conf}/static|]+staticRoot :: AppConfig DefaultEnv Extra -> Text+staticRoot conf = case extraStaticRoot $ appExtra conf of+                    Just root -> root+                    Nothing -> [st|#{appRoot conf}/static|]  -- | Settings for 'widgetFile', such as which template languages to support and -- default Hamlet settings.@@ -75,11 +77,13 @@               widgetFileSettings  data Extra = Extra-    { extraCopyright :: Text-    , extraAnalytics :: Maybe Text -- ^ Google Analytics+    { extraCopyright  :: Text+    , extraAnalytics  :: Maybe Text -- ^ Google Analytics+    , extraStaticRoot :: Maybe Text     } deriving Show  parseExtra :: DefaultEnv -> Object -> Parser Extra parseExtra _ o = Extra     <$> o .:  "copyright"     <*> o .:? "analytics"+    <*> o .:? "staticRoot"
hledger-web.cabal view
@@ -1,6 +1,6 @@ name:           hledger-web-version: 0.22.8-stability:      beta+version:        0.23+stability:      stable category:       Finance synopsis:       A web interface for the hledger accounting tool. description:    @@ -17,7 +17,7 @@ maintainer:     Simon Michael <simon@joyful.com> homepage:       http://hledger.org bug-reports:    http://hledger.org/bugs-tested-with:    GHC==7.6.3+tested-with:    GHC==7.4.2, GHC==7.6.3, GHC==7.8.2 cabal-version:  >= 1.8 build-type:     Simple extra-tmp-files:@@ -71,7 +71,7 @@     Default:       False  library-    cpp-options:   -DVERSION="0.22.8"+    cpp-options:   -DVERSION="0.23"     if flag(dev) || flag(library-only)         cpp-options: -DDEVELOPMENT  @@ -114,8 +114,8 @@                      Hledger.Web.Options                      -- Setup -- stops yesod devel complaining, requires build-depends: Cabal     build-depends:-                     hledger              == 0.22.2-                   , hledger-lib          == 0.22.2+                     hledger              == 0.23+                   , hledger-lib          == 0.23                    , base                 >= 4 && < 5                    , bytestring                    , clientsession@@ -172,7 +172,7 @@     if flag(library-only)         Buildable: False -    cpp-options:   -DVERSION="0.22.8"+    cpp-options:   -DVERSION="0.23"     if flag(dev)         cpp-options:   -DDEVELOPMENT @@ -181,8 +181,6 @@         ghc-options:   -threaded     if flag(dev)         ghc-options:   -O0-    else-        ghc-options:   -O2      extensions:                  CPP@@ -216,8 +214,8 @@                      Hledger.Web.Options      build-depends:-                     hledger              == 0.22.2-                   , hledger-lib          == 0.22.2+                     hledger              == 0.23+                   , hledger-lib          == 0.23                    , base                 >= 4 && < 5                    , bytestring                    , clientsession
static/jquery.url.js view
@@ -1,164 +1,181 @@-// JQuery URL Parser plugin - https://github.com/allmarkedup/jQuery-URL-Parser+// JQuery URL Parser // Written by Mark Perkins, mark@allmarkedup.com // License: http://unlicense.org/ (i.e. do what you want with it!) -;(function($, undefined) {-    -    var tag2attr = {-        a       : 'href',-        img     : 'src',-        form    : 'action',-        base    : 'href',-        script  : 'src',-        iframe  : 'src',-        link    : 'href'-    },-    -	key = ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","fragment"], // keys available to query+jQuery.url = function()+{+	var segments = {}; 	-	aliases = { "anchor" : "fragment" }, // aliases for backwards compatability--	parser = {-		strict  : /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,  //less intuitive, more accurate to the specs-		loose   :  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs-	},+	var parsed = {}; 	-	querystring_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g, // supports both ampersand and semicolon-delimted query string key/value pairs+	/**+    * Options object. Only the URI and strictMode values can be changed via the setters below.+    */+  	var options = { 	-	fragment_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g; // supports both ampersand and semicolon-delimted fragment key/value pairs+		url : window.location, // default URI is the page in which the script is running+		+		strictMode: false, // 'loose' parsing by default 	-	function parseUri( url, strictMode )-	{-		var str = decodeURI( url ),-		    res   = parser[ strictMode || false ? "strict" : "loose" ].exec( str ),-		    uri = { attr : {}, param : {}, seg : {} },-		    i   = 14;+		key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], // keys available to query  		-		while ( i-- )-		{-			uri.attr[ key[i] ] = res[i] || "";-		}+		q: {+			name: "queryKey",+			parser: /(?:^|&|;)([^&=;]*)=?([^&;]*)/g+		}, 		-		// build query and fragment parameters+		parser: {+			strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,  //less intuitive, more accurate to the specs+			loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs+		} 		-		uri.param['query'] = {};-		uri.param['fragment'] = {};+	};+	+    /**+     * Deals with the parsing of the URI according to the regex above.+ 	 * Written by Steven Levithan - see credits at top.+     */		+	var parseUri = function()+	{+		str = decodeURI( options.url ); 		-		uri.attr['query'].replace( querystring_parser, function ( $0, $1, $2 ){-			if ($1)-			{-				uri.param['query'][$1] = $2;+		var m = options.parser[ options.strictMode ? "strict" : "loose" ].exec( str );+		var uri = {};+		var i = 14;++		while ( i-- ) {+			uri[ options.key[i] ] = m[i] || "";+		}++		uri[ options.q.name ] = {};+		uri[ options.key[12] ].replace( options.q.parser, function ( $0, $1, $2 ) {+			if ($1) {+				uri[options.q.name][$1] = $2; 			} 		});-		-		uri.attr['fragment'].replace( fragment_parser, function ( $0, $1, $2 ){-			if ($1)++		return uri;+	};++    /**+     * Returns the value of the passed in key from the parsed URI.+  	 * +	 * @param string key The key whose value is required+     */		+	var key = function( key )+	{+		if ( jQuery.isEmptyObject(parsed) )+		{+			setUp(); // if the URI has not been parsed yet then do this first...	+		} +		if ( key == "base" )+		{+			if ( parsed.port !== null && parsed.port !== "" ) 			{-				uri.param['fragment'][$1] = $2;+				return parsed.protocol+"://"+parsed.host+":"+parsed.port+"/";	 			}-		});-				-		// split path and fragement into segments-		-        uri.seg['path'] = uri.attr.path.replace(/^\/+|\/+$/g,'').split('/');-        -        uri.seg['fragment'] = uri.attr.fragment.replace(/^\/+|\/+$/g,'').split('/');-        -        // compile a 'base' domain attribute-        -        uri.attr['base'] = uri.attr.host ? uri.attr.protocol+"://"+uri.attr.host + (uri.attr.port ? ":"+uri.attr.port : '') : '';-        -		return uri;+			else+			{+				return parsed.protocol+"://"+parsed.host+"/";+			}+		}+	+		return ( parsed[key] === "" ) ? null : parsed[key]; 	}; 	-	function getAttrName( elm )+	/**+     * Returns the value of the required query string parameter.+  	 * +	 * @param string item The parameter whose value is required+     */		+	var param = function( item ) 	{-		var tn = elm.tagName;-		if ( tn !== undefined ) return tag2attr[tn.toLowerCase()];-		return tn;-	}-	-	$.fn.url = function( strictMode )+		if ( jQuery.isEmptyObject(parsed) )+		{+			setUp(); // if the URI has not been parsed yet then do this first...	+		}+		if ( item === undefined )+		{+            return parsed.queryKey;+        }+        else+        {+            return ( parsed.queryKey[item] === null ) ? null : parsed.queryKey[item];+        }+	};++    /**+     * 'Constructor' (not really!) function.+     *  Called whenever the URI changes to kick off re-parsing of the URI and splitting it up into segments. +     */	+	var setUp = function() 	{-	    var url = '';-	    -	    if ( this.length )-	    {-	        url = $(this).attr( getAttrName(this[0]) ) || '';-	    }-	    -        return $.url({ url : url, strict : strictMode });+		parsed = parseUri();+		+		getSegments();	 	}; 	-	$.url = function( opts )+    /**+     * Splits up the body of the URI into segments (i.e. sections delimited by '/')+     */+	var getSegments = function() 	{-	    var url     = '',-	        strict  = false;--	    if ( typeof opts === 'string' )-	    {-	        url = opts;-	    }-	    else-	    {-	        opts = opts || {};-	        strict = opts.strict || strict;-            url = opts.url === undefined ? window.location.toString() : opts.url;-	    }-	    	            -        return {-            -            data : parseUri(url, strict),-            -            // get various attributes from the URI-            attr : function( attr )-            {-                attr = aliases[attr] || attr;-                return attr !== undefined ? this.data.attr[attr] : this.data.attr;-            },-            -            // return query string parameters-            param : function( param )-            {-                return param !== undefined ? this.data.param.query[param] : this.data.param.query;-            },-            -            // return fragment parameters-            fparam : function( param )-            {-                return param !== undefined ? this.data.param.fragment[param] : this.data.param.fragment;-            },-            -            // return path segments-            segment : function( seg )-            {-                if ( seg === undefined )-                {-                    return this.data.seg.path;                    -                }-                else-                {-                    seg = seg < 0 ? this.data.seg.path.length + seg : seg - 1; // negative segments count from the end-                    return this.data.seg.path[seg];                    -                }-            },-            -            // return fragment segments-            fsegment : function( seg )-            {-                if ( seg === undefined )-                {-                    return this.data.seg.fragment;                    -                }-                else-                {-                    seg = seg < 0 ? this.data.seg.fragment.length + seg : seg - 1; // negative segments count from the end-                    return this.data.seg.fragment[seg];                    -                }-            }-            -        };-        +		var p = parsed.path;+		segments = []; // clear out segments array+		segments = parsed.path.length == 1 ? {} : ( p.charAt( p.length - 1 ) == "/" ? p.substring( 1, p.length - 1 ) : path = p.substring( 1 ) ).split("/"); 	}; 	-})(jQuery);+	return {+		+	    /**+	     * Sets the parsing mode - either strict or loose. Set to loose by default.+	     *+	     * @param string mode The mode to set the parser to. Anything apart from a value of 'strict' will set it to loose!+	     */+		setMode : function( mode )+		{+			options.strictMode = mode == "strict" ? true : false;+			return this;+		},+		+		/**+	     * Sets URI to parse if you don't want to to parse the current page's URI.+		 * Calling the function with no value for newUri resets it to the current page's URI.+	     *+	     * @param string newUri The URI to parse.+	     */		+		setUrl : function( newUri )+		{+			options.url = newUri === undefined ? window.location : newUri;+			setUp();+			return this;+		},		+		+		/**+	     * Returns the value of the specified URI segment. Segments are numbered from 1 to the number of segments.+		 * For example the URI http://test.com/about/company/ segment(1) would return 'about'.+		 *+		 * If no integer is passed into the function it returns the number of segments in the URI.+	     *+	     * @param int pos The position of the segment to return. Can be empty.+	     */	+		segment : function( pos )+		{+			if ( jQuery.isEmptyObject(parsed) )+			{+				setUp(); // if the URI has not been parsed yet then do this first...	+			} +			if ( pos === undefined )+			{+				return segments.length;+			}+			return ( segments[pos] === "" || segments[pos] === undefined ) ? null : segments[pos];+		},+		+		attr : key, // provides public access to private 'key' function - see above+		+		param : param // provides public access to private 'param' function - see above+		+	};+	+}();