hledger-web 0.22.4 → 0.22.5
raw patch · 8 files changed
+183/−206 lines, 8 filesdep ~http-clientdep ~warp
Dependency ranges changed: http-client, warp
Files
- CHANGES +24/−0
- CHANGES.md +0/−19
- Foundation.hs +6/−6
- Hledger/Web/Main.hs +1/−3
- Hledger/Web/Options.hs +0/−5
- Settings.hs +4/−8
- hledger-web.cabal +8/−8
- static/jquery.url.js +140/−157
+ CHANGES view
@@ -0,0 +1,24 @@+0.22.5 (2014/4/15)++- allow http-client 0.3.*, fixing cabal install again with GHC <= 7.6 (not yet 7.8)+- use pretty-show only with GHC 7.4+, fixing GHC 7.2 (fixes #155)+- allow warp 2.1, fixing cabal install++0.22.4 (2014/2/10)++- Fix: include the right unminified version of jquery.url.js (1.1) to avoid js breakage++0.22.3 (2014/2/10)++- Fix: version number reported by --version++0.22.2 (2014/2/10)++- new option --static-root to set the base url for static files+- allow blaze-html 0.7 (#159)+- Fix: include unminified source of all javascript to help packagers (#161)+- Fix: work around clang-related build failures with OS X mavericks/XCode 5++0.22.1 (2014/1/6) and older++See http://hledger.org/release-notes or doc/CHANGES.md.
− CHANGES.md
@@ -1,19 +0,0 @@-## 2014/2/10 hledger-web 0.22.4--* web: include the right unminified version of jquery.url.js (1.1) to avoid js breakage--## 2014/2/10 hledger-web 0.22.3--* web: fix version number reported by --version--## 2014/2/10 hledger-web 0.22.2--New:--* web: new option `--static-root` to set the base url for static files--Improved:--* web: include unminified source of all javascript to help packagers (fixes #161)-* web: work around clang-related build failures with OS X mavericks/XCode 5-* web: allow blaze-html 0.7 (closes #159)
Foundation.hs view
@@ -19,7 +19,7 @@ -- import qualified Settings import Settings.Development (development) import Settings.StaticFiles-import Settings (staticRoot, widgetFile, Extra (..))+import Settings (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
Hledger/Web/Main.hs view
@@ -20,7 +20,6 @@ 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,13 +59,12 @@ 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 = HostIPv4- ,appExtra = Extra "" Nothing staticRoot+ ,appExtra = Extra "" Nothing } if server_ opts then do
Hledger/Web/Options.hs view
@@ -1,7 +1,6 @@ module Hledger.Web.Options where import Prelude-import Control.Applicative ((<$>)) import Data.Maybe import System.Console.CmdArgs import System.Console.CmdArgs.Explicit@@ -27,7 +26,6 @@ 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++")")- ,flagReq ["static-root"] (\s opts -> Right $ setopt "static-root" s opts) "Static Root" ("The root url from which the static files will be loaded (default: BASE_URL/static)") ] webmode :: Mode [([Char], [Char])]@@ -49,7 +47,6 @@ server_ :: Bool ,base_url_ :: String ,port_ :: Int- ,static_root_ :: Maybe String ,cliopts_ :: CliOpts } deriving (Show) @@ -59,7 +56,6 @@ def def def- def -- instance Default WebOpts where def = defwebopts @@ -71,7 +67,6 @@ 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,10 +54,8 @@ -- have to make a corresponding change here. -- -- To see how this value is used, see urlRenderOverride in Foundation.hs-staticRoot :: AppConfig DefaultEnv Extra -> Text-staticRoot conf = case extraStaticRoot $ appExtra conf of- Just root -> root- Nothing -> [st|#{appRoot conf}/static|]+staticRoot :: AppConfig DefaultEnv x -> Text+staticRoot conf = [st|#{appRoot conf}/static|] -- | Settings for 'widgetFile', such as which template languages to support and -- default Hamlet settings.@@ -77,13 +75,11 @@ widgetFileSettings data Extra = Extra- { extraCopyright :: Text- , extraAnalytics :: Maybe Text -- ^ Google Analytics- , extraStaticRoot :: Maybe Text+ { extraCopyright :: Text+ , extraAnalytics :: Maybe Text -- ^ Google Analytics } deriving Show parseExtra :: DefaultEnv -> Object -> Parser Extra parseExtra _ o = Extra <$> o .: "copyright" <*> o .:? "analytics"- <*> o .:? "staticRoot"
hledger-web.cabal view
@@ -1,5 +1,5 @@ name: hledger-web-version: 0.22.4+version: 0.22.5 stability: beta category: Finance synopsis: A web interface for the hledger accounting tool.@@ -48,7 +48,7 @@ templates/homepage.julius templates/homepage.lucius templates/normalize.lucius- CHANGES.md+ CHANGES source-repository head type: git@@ -71,7 +71,7 @@ Default: False library- cpp-options: -DVERSION="0.22.4"+ cpp-options: -DVERSION="0.22.5" if flag(dev) || flag(library-only) cpp-options: -DDEVELOPMENT @@ -126,7 +126,7 @@ , hamlet , hjsmin , http-conduit- , http-client >= 0.2 && < 0.3+ , http-client >= 0.2 && < 0.4 , HUnit , network-conduit , old-locale@@ -141,7 +141,7 @@ , wai , wai-extra , wai-handler-launch >= 1.3 && < 2.1- , warp >= 1.3 && < 2.1+ , warp >= 1.3 && < 2.2 , yaml , yesod >= 1.2 && < 1.3 , yesod-core@@ -162,7 +162,7 @@ if flag(library-only) Buildable: False - cpp-options: -DVERSION="0.22.4"+ cpp-options: -DVERSION="0.22.5" if flag(dev) cpp-options: -DDEVELOPMENT @@ -218,7 +218,7 @@ , hamlet , hjsmin , http-conduit- , http-client >= 0.2 && < 0.3+ , http-client >= 0.2 && < 0.4 , HUnit , network-conduit , old-locale@@ -233,7 +233,7 @@ , wai , wai-extra , wai-handler-launch >= 1.3 && < 2.1- , warp >= 1.3 && < 2.1+ , warp >= 1.3 && < 2.2 , yaml , yesod >= 1.2 && < 1.3 , yesod-core
static/jquery.url.js view
@@ -1,181 +1,164 @@-// JQuery URL Parser+// JQuery URL Parser plugin - https://github.com/allmarkedup/jQuery-URL-Parser // Written by Mark Perkins, mark@allmarkedup.com // License: http://unlicense.org/ (i.e. do what you want with it!) -jQuery.url = function()-{- var segments = {};+;(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 - var parsed = {};+ 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+ }, - /**- * Options object. Only the URI and strictMode values can be changed via the setters below.- */- var options = {+ querystring_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g, // supports both ampersand and semicolon-delimted query string key/value pairs - url : window.location, // default URI is the page in which the script is running- - strictMode: false, // 'loose' parsing by default+ fragment_parser = /(?:^|&|;)([^&=;]*)=?([^&;]*)/g; // supports both ampersand and semicolon-delimted fragment key/value pairs - key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], // keys available to query - - q: {- name: "queryKey",- parser: /(?:^|&|;)([^&=;]*)=?([^&;]*)/g- },+ function parseUri( url, strictMode )+ {+ var str = decodeURI( url ),+ res = parser[ strictMode || false ? "strict" : "loose" ].exec( str ),+ uri = { attr : {}, param : {}, seg : {} },+ i = 14; - parser: {- strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, //less intuitive, more accurate to the specs- loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ // more intuitive, fails on relative paths and deviates from specs+ while ( i-- )+ {+ uri.attr[ key[i] ] = res[i] || ""; } - };- - /**- * 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 );+ // build query and fragment parameters - 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;- }- });-- 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['query'] = {};+ uri.param['fragment'] = {};+ + uri.attr['query'].replace( querystring_parser, function ( $0, $1, $2 ){+ if ($1) {- return parsed.protocol+"://"+parsed.host+":"+parsed.port+"/"; + uri.param['query'][$1] = $2; }- else+ });+ + uri.attr['fragment'].replace( fragment_parser, function ( $0, $1, $2 ){+ if ($1) {- return parsed.protocol+"://"+parsed.host+"/";+ uri.param['fragment'][$1] = $2; }- }- - return ( parsed[key] === "" ) ? null : parsed[key];+ });+ + // 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; }; - /**- * Returns the value of the required query string parameter.- * - * @param string item The parameter whose value is required- */ - var param = function( item )- {- 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()+ function getAttrName( elm ) {- parsed = parseUri();- - getSegments(); - };+ var tn = elm.tagName;+ if ( tn !== undefined ) return tag2attr[tn.toLowerCase()];+ return tn;+ } - /**- * Splits up the body of the URI into segments (i.e. sections delimited by '/')- */- var getSegments = function()+ $.fn.url = function( strictMode ) {- 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("/");+ var url = '';+ + if ( this.length )+ {+ url = $(this).attr( getAttrName(this[0]) ) || '';+ }+ + return $.url({ url : url, strict : strictMode }); }; - 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- + $.url = function( opts )+ {+ 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]; + }+ }+ + };+ }; -}();+})(jQuery);