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 +38/−10
- Yst/Build.hs +16/−11
- Yst/Config.hs +3/−3
- Yst/Data.hs +25/−6
- Yst/Render.hs +13/−7
- Yst/Sqlite3.hs +27/−0
- Yst/Types.hs +4/−3
- Yst/Util.hs +19/−1
- changelog +7/−0
- demo/config.yaml +2/−2
- demo/date.st +0/−1
- demo/event.st +0/−2
- demo/eventgroup.st +0/−5
- demo/files/css/base-min.css +0/−7
- demo/files/css/reset-fonts-grids.css +0/−7
- demo/files/css/reset-min.css +0/−7
- demo/templates/date.st +1/−0
- demo/templates/event.st +2/−0
- demo/templates/eventgroup.st +5/−0
- demo/yahoo/css/base-min.css +7/−0
- demo/yahoo/css/reset-fonts-grids.css +7/−0
- demo/yahoo/css/reset-min.css +7/−0
- yst.cabal +20/−12
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