packages feed

yst 0.2.4.1 → 0.3

raw patch · 23 files changed

+203/−84 lines, 23 filesdep +HDBCdep +HDBC-sqlite3dep ~HStringTemplate

Dependencies added: HDBC, HDBC-sqlite3

Dependency ranges changed: HStringTemplate

Files

README.markdown view
@@ -2,7 +2,8 @@ ======================================================  `yst` is a tool for generating a static website by filling [string-template][]s with data taken from [YAML][] or [CSV][] text files. This approach+template][]s with data taken from [YAML][] or [CSV][] text files or +[SQLite3][] file based databases. This approach combines the speed, security, and ease of deployment of a static website with the flexibility and maintainability of a dynamic site that separates presentation and data.@@ -175,13 +176,19 @@  - `indexfile`: the filename of the index file (default: `index.yaml`) - `title`:  the title of the whole site-- `sourcedir`:  the directory containing all the templates and page sources+- `sourcedir`:  list of directories containing templates and page sources   (default: `.`)-- `datadir`:  the directory containing yaml data files (default: `.`)-- `filesdir`: the directory containing static files (default: `files`)+- `datadir`:  list of directories containing yaml data files (default: `.`)+- `filesdir`: list of directories containing static files (default: `files`) - `layout`: the default layout template for the site, relative to   `sourcedir` (default: `layout.html.st`) +The directories specified by `sourcedir` and `datadir` are searched in+order to find source/template or data files, respectively.  This allows+for a `../templates` directory to be shared among multiple sites, for+example.  Static files are merged from the contents of all directories+in `filesdir`. All of these accept a string as a singleton list.+ ### `index.yaml` and submenus  The index file is a YAML list of pages. Each page may have the following@@ -221,20 +228,26 @@  ### The `data` field -The `data` field in `index.yaml` can populate any number of stringtemplate-attributes with data from YAML or CSV files.  The syntax is easiest to-explain by example (note that the keywords do not have to be in ALL CAPS,-although they may, and the query doesn't have to end with a semicolon,-though it may):+The `data` field in `index.yaml` can populate any number of+stringtemplate attributes with data from YAML or CSV files or SQLite3+databases.  The syntax is easiest to explain by example (note that the+keywords do not have to be in ALL CAPS, although they may, and the+query doesn't have to end with a semicolon, though it may):      data:         events:  from events.yaml order by date desc group by title then location         people:  from people.csv order by birthday then lastname where                   birthstate = 'CA' limit 5+        beststudents: from students.sqlite +                  query "select * from students where grade > 5"+                  order by name  First we have the name of the stringtemplate attribute to be populated (say, `events`).  Then, after the colon, we have the data source-(`events.yaml`) followed by one or more *transformations*, which will+(`events.yaml`). If the data source is an SQLite3 database, it should be+followed by a query that is a quoted string.++The data source is followed by  one or more *transformations*, which will be applied in order.  Here are the possible transformations.  In what follows, brackets denote an optional component, `|` denotes alternatives, and `*` indicates that the component may be repeated@@ -438,6 +451,20 @@ (Thanks to <http://www.terminally-incoherent.com/blog/2006/07/20/dump-mysql-table-into-csv-file/>.) +### Using a SQLite database as data source++You can also get the data directly from a database. Just give the file+name from the database followed by a query quoted in "'s++In this way you can do joins and other advanced operations on your+data before handing them over to yst:++    data:+      meetings : FROM data.sqlite +                 QUERY "select * from meetings +                   left outer join persons+                   on meetings.speaker = persons.name"+ ### Using HTML in the templates  Markdown allows raw HTML to be used, so you can embed HTML in templates.@@ -528,6 +555,7 @@ [string template]: http://www.stringtemplate.org/ [YAML]: http://www.yaml.org/ [CSV]: http://en.wikipedia.org/wiki/Comma-separated_values+[SQLite3]: http://www.sqlite.org/ [cabal install]: http://hackage.haskell.org/trac/hackage/wiki/CabalInstall [Haskell platform]: http://hackage.haskell.org/platform/ [markdown]: http://daringfireball.com/markdown
Yst/Build.hs view
@@ -39,25 +39,30 @@ import System.IO (stderr) import Control.Monad -dependencies :: Site -> String -> [FilePath]-dependencies site url =+findSource :: Site -> FilePath -> IO FilePath+findSource = searchPath . sourceDir++dependencies :: Site -> String -> IO [FilePath]+dependencies site url = do   let page = case M.lookup url (pageIndex site) of                   Nothing   -> error $ "Tried to get dependencies for nonexistent page: " ++ url                   Just pg   -> pg-      layout = sourceDir site </> stripStExt (fromMaybe (defaultLayout site) $ layoutFile page) <.> "st"-      requires = map (sourceDir site </>) $ requiresFiles page-      srcdir = sourceDir site </>+  layout <- findSource site $ stripStExt (fromMaybe (defaultLayout site) $ layoutFile page) <.> "st"+  requires <- mapM (findSource site) $ requiresFiles page+  srcdir <- findSource site $                  case sourceFile page of                        TemplateFile f -> stripStExt f <.> "st"                        SourceFile f   -> f-      fileFromSpec (DataFromFile f _) = Just f+  let fileFromSpec (DataFromFile f _) = Just f+      fileFromSpec (DataFromSqlite3 f _ _) = Just f       fileFromSpec _ = Nothing-      dataFiles = map (dataDir site </>) $ mapMaybe (\(_,s) -> fileFromSpec s) $ pageData page-  in  indexFile site : layout : srcdir : (requires ++ dataFiles)+  dataFiles <- mapM (searchPath $ dataDir site) $ mapMaybe (\(_,s) -> fileFromSpec s) $ pageData page+  return $ indexFile site : layout : srcdir : (requires ++ dataFiles)  buildSite :: Site -> IO () buildSite site = do-  files <- liftM (filter (/=".") . map (makeRelative $ filesDir site)) $ getDirectoryContentsRecursive $ filesDir site+  let filesIn dir = liftM (filter (/=".") . map (makeRelative dir)) $ getDirectoryContentsRecursive dir+  files <- liftM concat $ mapM filesIn $ filesDir site   let pages = M.keys $ pageIndex site   let overlap = files `intersect` pages   unless (null overlap) $ forM_ overlap@@ -72,7 +77,7 @@ updateFile :: Site -> FilePath -> IO () updateFile site file = do   let destpath = deployDir site </> file-  let srcpath = filesDir site </> file+  srcpath <- searchPath (filesDir site) file   srcmod <- getModificationTime srcpath   destmod <- catch (getModificationTime destpath) (\_ -> return $ TOD 0 0)   if srcmod > destmod@@ -85,7 +90,7 @@ updatePage :: Site -> Page -> IO () updatePage site page = do   let destpath = deployDir site </> pageUrl page-  let deps = dependencies site $ pageUrl page+  deps <- dependencies site $ pageUrl page   forM_ deps $ \dep -> do     exists <- doesFileExist dep     unless exists $ do
Yst/Config.hs view
@@ -33,9 +33,9 @@          let indexfile = getStrAttrWithDefault "indexfile" "index.yaml" xs          (ind, nav) <- parseIndexFile indexfile          return Site{ siteTitle     = getStrAttrWithDefault "title" "" xs-                    , sourceDir     = getStrAttrWithDefault "sourcedir" "." xs-                    , dataDir       = getStrAttrWithDefault "datadir" "." xs-                    , filesDir      = getStrAttrWithDefault "filesdir" "files" xs+                    , sourceDir     = getStrListWithDefault "sourcedir" "." xs+                    , dataDir       = getStrListWithDefault "datadir" "." xs+                    , filesDir      = getStrListWithDefault "filesdir" "files" xs                     , deployDir     = getStrAttrWithDefault "deploydir" "site" xs                     , defaultLayout = getStrAttrWithDefault "layout" "layout" xs                     , indexFile     = indexfile
Yst/Data.hs view
@@ -23,18 +23,26 @@ import Yst.Util import Yst.Yaml import Yst.CSV+import Yst.Sqlite3 (readSqlite3) import Control.Monad import Data.Char import Data.Maybe (fromMaybe) import Data.List (sortBy, nub, isPrefixOf) import Text.ParserCombinators.Parsec-import System.FilePath (takeExtension, (</>))+import System.FilePath (takeExtension) +findData :: Site -> FilePath -> IO FilePath+findData = searchPath . dataDir+ getData :: Site -> DataSpec -> IO Node getData site (DataFromFile file opts) = do-  raw <- catch (readDataFile $  dataDir site </> file)+  raw <- catch (findData site file >>= readDataFile)           (\e -> errorExit 15 ("Error reading data from " ++ file ++ ": " ++ show e) >> return undefined)   return $ foldl applyDataOption raw opts+getData site (DataFromSqlite3 database query opts) = do+  raw <- catch (findData site database >>= \d -> readSqlite3 d query)+          (\e -> errorExit 15 ("Error reading Sqlite3 database from " ++ database ++ ": " ++ show e) >> return undefined)+  return $ foldl applyDataOption raw opts getData _ (DataConstant n) = return n  readDataFile :: FilePath -> IO Node@@ -103,18 +111,20 @@  parseDataField :: Node -> DataSpec parseDataField n@(NString s) = case parse pDataField s s of-  Right (f,opts)  -> DataFromFile f opts+  Right (f, Nothing, opts)  -> DataFromFile f opts+  Right (f, Just query, opts) -> DataFromSqlite3 f query opts   Left err        -> if "from" `isPrefixOf` (dropWhile isSpace $ map toLower s)                         then error $ "Error parsing data field: " ++ show err                         else DataConstant n  parseDataField n = DataConstant n -pDataField :: GenParser Char st ([Char], [DataOption])+pDataField :: GenParser Char st (String, Maybe String,[DataOption]) pDataField = do   spaces   pString "from"   pSpace-  fname <- pIdentifier <?> "name of YAML or CSV file"+  fname <- pIdentifier <?> "name of YAML, CSV or SQLite3 file"+  query <- (optionMaybe $ pQuery) <?> "a SQL query"   opts <- many $ (pOptWhere <?> "where [CONDITION]")               <|> (pOptLimit <?> "limit [NUMBER]")               <|> (pOptOrderBy <?> "order by [CONDITION]")@@ -123,7 +133,7 @@   optional $ char ';'   spaces   eof-  return (fname, opts)+  return (fname, query, opts)  pIdentifier :: GenParser Char st [Char] pIdentifier = spaces >> (pQuoted '\'' <|> pQuoted '"' <|> many (noneOf " \t\n<>=;,'\""))@@ -141,6 +151,15 @@   char delim   res <- many (noneOf [delim] <|> (try $ char '\\' >> char delim))   char delim+  return res++pQuery :: GenParser Char st String+pQuery = try $ do+  optional $ oneOf ",;"+  spaces+  pString "query"+  pSpace+  res <- pQuoted '"'   return res  pOptLimit :: GenParser Char st DataOption
Yst/Render.hs view
@@ -100,26 +100,32 @@                              ".txt"   -> PlainFormat                              ".markdown" -> PlainFormat                              _       -> HtmlFormat+ renderPage :: Site -> Page -> IO String renderPage site page = do   let menuHtml = renderNav (pageUrl page) (navigation site)   let layout = fromMaybe (defaultLayout site) $ layoutFile page-  srcDir <- canonicalizePath $ sourceDir site-  g <- directoryGroupRecursive srcDir+  srcDirs <- mapM canonicalizePath $ sourceDir site+  gs <- mapM directoryGroupRecursive srcDirs+  let g = foldl1 mergeSTGroups gs   attrs <- forM (pageData page) $ \(k, v) -> getData site v >>= \n -> return (k,n)   todaysDate <- liftM utctDay getCurrentTime+  let root' = case length (filter (=='/') $ pageUrl page) of+                    0  -> ""+                    n  -> concat $ replicate n "../"   rawContents <-     case sourceFile page of-          SourceFile sf   -> liftM (filter (/='\r')) $ readFile (srcDir </> sf)+          SourceFile sf   -> liftM (filter (/='\r')) $ searchPath srcDirs sf >>= readFile           TemplateFile tf -> do             templ <- getTemplate tf g-            return $ render (setManyAttrib attrs templ)+            return $ render+                    . setManyAttrib attrs+                    . setAttribute "root" root'+                    . setAttribute "gendate" todaysDate+                    $ templ   layoutTempl <- getTemplate layout g   let format = formatFromExtension (stripStExt layout)   let contents = converterForFormat format rawContents-  let root' = case length (filter (=='/') $ pageUrl page) of-                    0  -> ""-                    n  -> concat $ replicate n "../"   return $ render          . setManyAttrib attrs          . setAttribute "sitetitle" (siteTitle site)
+ Yst/Sqlite3.hs view
@@ -0,0 +1,27 @@+module Yst.Sqlite3 (readSqlite3)+where++import Database.HDBC+import Database.HDBC.Sqlite3+import Data.Maybe+import Yst.Types+import Yst.Util (parseAsDate)++readSqlite3 :: FilePath -> String -> IO Node+readSqlite3 filename query = do+  conn <- connectSqlite3 filename+  stmt <- prepare conn query+  execute stmt []+  records <- sFetchAllRows' stmt+  fieldNames <- getColumnNames stmt+  disconnect conn+         +  return $ NList $ map (NMap .+                       (zip fieldNames) .+                       (map (fieldToNode . fromMaybe ""))) records++fieldToNode :: String -> Node+fieldToNode s =+  case parseAsDate s of+       Nothing -> NString s+       Just d  -> NDate d
Yst/Types.hs view
@@ -26,9 +26,9 @@  data Site = Site {     siteTitle     :: String-  , sourceDir     :: FilePath-  , dataDir       :: FilePath-  , filesDir      :: FilePath+  , sourceDir     :: [FilePath]+  , dataDir       :: [FilePath]+  , filesDir      :: [FilePath]   , deployDir     :: FilePath   , defaultLayout :: FilePath   , indexFile     :: FilePath@@ -75,6 +75,7 @@  data DataSpec = DataConstant Node               | DataFromFile FilePath [DataOption]+              | DataFromSqlite3 FilePath String [DataOption]               deriving (Show, Read, Eq)  data DataOption = OrderBy [(String, SortDirection)]
Yst/Util.hs view
@@ -16,7 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA -} -module Yst.Util (stripBlanks, parseAsDate, stripStExt, getStrAttrWithDefault, fromNString, getDirectoryContentsRecursive, errorExit)+module Yst.Util (stripBlanks, parseAsDate, stripStExt, getStrAttrWithDefault, getStrListWithDefault, fromNString, getDirectoryContentsRecursive, searchPath, errorExit) where import Yst.Types import System.Exit@@ -59,6 +59,17 @@         Just _             -> error $ attr ++ " must have string value."         Nothing            -> def +getStrListWithDefault :: String -> String -> [(String, Node)] -> [String]+getStrListWithDefault attr def xs =+  case lookup attr xs of+    Just (NString s) -> [s]+    Just (NList ys) -> map nodeToString ys+    Just _ -> formatError+    Nothing -> [def]+  where nodeToString (NString s) = s+        nodeToString _ = formatError+        formatError = error $ attr ++ " must be a string or list of strings."+ fromNString :: Node -> String fromNString (NString s) = s fromNString x = error $ "Expected string value, got " ++ show x@@ -73,6 +84,13 @@        children <- mapM getDirectoryContentsRecursive contents'        return (concat children)      else return [path]++searchPath :: [FilePath] -> FilePath -> IO FilePath+searchPath [] file = return file       -- may or may not exist, but we tried.+searchPath (dir:dirs) file = do+  exists <- doesFileExist curFile+  if exists then return curFile else searchPath dirs file+    where curFile = dir </> file  errorExit :: Int -> String -> IO () errorExit lvl msg = hPutStrLn stderr msg >> exitWith (ExitFailure lvl)
+ changelog view
@@ -0,0 +1,7 @@+yst 0.3 (released 20 Oct 2012)++  * Added support for loading data from Sqlite3 databases.+    (Sigurd Meldgaard)++  * Allow `sourcedir`, `datadir`, `filesdir` to specify a list+    of directories, searched in order. (Christopher League)
demo/config.yaml view
@@ -1,6 +1,6 @@ indexfile: index.yaml title: My Website-templatedir: .+sourcedir: [., templates] datadir: .-filesdir: files+filesdir: [files, yahoo] layout: layout.html.st
− demo/date.st
@@ -1,1 +0,0 @@-$it; format="%B %d, %Y"$
− demo/event.st
@@ -1,2 +0,0 @@-- $if(it.speaker)$$it.speaker; separator=" and "$, $endif$ *$it.title$*.-
− demo/eventgroup.st
@@ -1,5 +0,0 @@-**$first(it).date:date(); separator=" - "$**---$it:event()$-
− demo/files/css/base-min.css
@@ -1,7 +0,0 @@-/*-Copyright (c) 2009, Yahoo! Inc. All rights reserved.-Code licensed under the BSD License:-http://developer.yahoo.net/yui/license.txt-version: 2.7.0-*/-body{margin:10px;}h1{font-size:138.5%;}h2{font-size:123.1%;}h3{font-size:108%;}h1,h2,h3{margin:1em 0;}h1,h2,h3,h4,h5,h6,strong,dt{font-weight:bold;}optgroup{font-weight:normal;}abbr,acronym{border-bottom:1px dotted #000;cursor:help;}em{font-style:italic;}del{text-decoration:line-through;}blockquote,ul,ol,dl{margin:1em;}ol,ul,dl{margin-left:2em;}ol li{list-style:decimal outside;}ul li{list-style:disc outside;}dl dd{margin-left:1em;}th,td{border:1px solid #000;padding:.5em;}th{font-weight:bold;text-align:center;}caption{margin-bottom:.5em;text-align:center;}sup{vertical-align:super;}sub{vertical-align:sub;}p,fieldset,table,pre{margin-bottom:1em;}button,input[type="checkbox"],input[type="radio"],input[type="reset"],input[type="submit"]{padding:1px;}
− demo/files/css/reset-fonts-grids.css
@@ -1,7 +0,0 @@-/*-Copyright (c) 2009, Yahoo! Inc. All rights reserved.-Code licensed under the BSD License:-http://developer.yahoo.net/yui/license.txt-version: 2.7.0-*/-html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}body{text-align:center;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main,.yui-g .yui-u .yui-g{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-g .yui-u{width:48.1%;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}.yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#hd:after,#bd:after,#ft:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#hd,#bd,#ft,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;}
− demo/files/css/reset-min.css
@@ -1,7 +0,0 @@-/*-Copyright (c) 2009, Yahoo! Inc. All rights reserved.-Code licensed under the BSD License:-http://developer.yahoo.net/yui/license.txt-version: 2.7.0-*/-html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}
+ demo/templates/date.st view
@@ -0,0 +1,1 @@+$it; format="%B %d, %Y"$
+ demo/templates/event.st view
@@ -0,0 +1,2 @@+- $if(it.speaker)$$it.speaker; separator=" and "$, $endif$ *$it.title$*.+
+ demo/templates/eventgroup.st view
@@ -0,0 +1,5 @@+**$first(it).date:date(); separator=" - "$**+++$it:event()$+
+ demo/yahoo/css/base-min.css view
@@ -0,0 +1,7 @@+/*+Copyright (c) 2009, Yahoo! Inc. All rights reserved.+Code licensed under the BSD License:+http://developer.yahoo.net/yui/license.txt+version: 2.7.0+*/+body{margin:10px;}h1{font-size:138.5%;}h2{font-size:123.1%;}h3{font-size:108%;}h1,h2,h3{margin:1em 0;}h1,h2,h3,h4,h5,h6,strong,dt{font-weight:bold;}optgroup{font-weight:normal;}abbr,acronym{border-bottom:1px dotted #000;cursor:help;}em{font-style:italic;}del{text-decoration:line-through;}blockquote,ul,ol,dl{margin:1em;}ol,ul,dl{margin-left:2em;}ol li{list-style:decimal outside;}ul li{list-style:disc outside;}dl dd{margin-left:1em;}th,td{border:1px solid #000;padding:.5em;}th{font-weight:bold;text-align:center;}caption{margin-bottom:.5em;text-align:center;}sup{vertical-align:super;}sub{vertical-align:sub;}p,fieldset,table,pre{margin-bottom:1em;}button,input[type="checkbox"],input[type="radio"],input[type="reset"],input[type="submit"]{padding:1px;}
+ demo/yahoo/css/reset-fonts-grids.css view
@@ -0,0 +1,7 @@+/*+Copyright (c) 2009, Yahoo! Inc. All rights reserved.+Code licensed under the BSD License:+http://developer.yahoo.net/yui/license.txt+version: 2.7.0+*/+html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}body{text-align:center;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main,.yui-g .yui-u .yui-g{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-g .yui-u{width:48.1%;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}.yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#hd:after,#bd:after,#ft:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#hd,#bd,#ft,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;}
+ demo/yahoo/css/reset-min.css view
@@ -0,0 +1,7 @@+/*+Copyright (c) 2009, Yahoo! Inc. All rights reserved.+Code licensed under the BSD License:+http://developer.yahoo.net/yui/license.txt+version: 2.7.0+*/+html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}
yst.cabal view
@@ -1,13 +1,14 @@ name:                yst-version:             0.2.4.1+version:             0.3 Tested-With:         GHC == 6.10.4, GHC == 6.12.1-Cabal-version:       >= 1.2+Cabal-version:       >= 1.6 build-type:          Simple synopsis:            Builds a static website from templates and data in YAML or                      CSV files. description:         `yst` is a tool for generating a static website                      by filling string templates with data taken from-                     YAML text files (or, alternatively, CSV files).+                     YAML text files (or, alternatively, CSV files or +                     from a Sqlite3 database).                      This approach combines the speed, security, and                      ease of deployment of a static website with the                      flexibility and maintainability of a dynamic site@@ -21,12 +22,13 @@ homepage:            http://github.com/jgm/yst stability:           experimental data-files:          README.markdown+                     changelog                      demo/config.yaml-                     demo/date.st-                     demo/eventgroup.st+                     demo/templates/date.st+                     demo/templates/eventgroup.st                      demo/april_events.st                      demo/events.st-                     demo/event.st+                     demo/templates/event.st                      demo/events.yaml                      demo/index.st                      demo/index.yaml@@ -34,23 +36,29 @@                      demo/layout.tex.st                      demo/room101.txt                      demo/room203.txt-                     demo/files/css/base-min.css+                     demo/yahoo/css/base-min.css                      demo/files/css/hk-pyg.css                      demo/files/css/ie.css                      demo/files/css/print.css-                     demo/files/css/reset-fonts-grids.css-                     demo/files/css/reset-min.css+                     demo/yahoo/css/reset-fonts-grids.css+                     demo/yahoo/css/reset-min.css                      demo/files/css/screen.css                      demo/files/js/nav.js++Source-repository    head+  type:              git+  location:          git://github.com/jgm/yst.git+ Executable           yst   hs-source-dirs:    .   main-is:           yst.hs   other-modules:     Yst.Types, Yst.Yaml, Yst.Util, Yst.Data, Yst.Config,-                     Yst.Render, Yst.Build, Yst.CSV-  build-depends:     base >=3 && < 5, HStringTemplate >= 0.6.1, HsSyck, csv,+                     Yst.Render, Yst.Build, Yst.CSV, Yst.Sqlite3+  build-depends:     base >=3 && < 5, HStringTemplate >= 0.6.1 && < 0.6.9,+                     HsSyck, csv,                      filepath, containers, directory, utf8-string, time,                      old-locale, old-time, parsec, xhtml, pandoc, bytestring,-                     split+                     split, HDBC, HDBC-sqlite3   extensions:        CPP   if impl(ghc >= 6.12)     ghc-options:     -Wall -threaded -fno-warn-orphans -fno-warn-unused-do-bind