commit b5e34273bf5fd65f53e9a63dad0e07d609c7f7f2 Author: nek0 Date: Fri Nov 10 13:28:35 2017 +0100 init diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100644 index 0000000..9fa52f4 --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1,5 @@ +# Revision history for chaoszone + +## 0.0.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/Setup.hs b/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/chaoszone.cabal b/chaoszone.cabal new file mode 100644 index 0000000..eb84fc6 --- /dev/null +++ b/chaoszone.cabal @@ -0,0 +1,28 @@ +-- Initial chaoszone.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/ + +name: chaoszone +version: 0.0.0.0 +-- synopsis: +-- description: +homepage: https://chaoszone.cz +license: PublicDomain +author: nek0 +maintainer: nek0@chelnok.de +category: Web +build-type: Simple +extra-source-files: ChangeLog.md +cabal-version: >=1.10 + +executable chaoszone + main-is: Main.hs + -- other-modules: + other-extensions: OverloadedStrings + build-depends: base >=4.10 && <4.11 + , time >=1.7 + , filepath >=1.4 + , hakyll >=4.9.8.0 + , HTTP + , aeson + hs-source-dirs: src + default-language: Haskell2010 diff --git a/newpost.sh b/newpost.sh new file mode 100755 index 0000000..c20df0f --- /dev/null +++ b/newpost.sh @@ -0,0 +1,36 @@ +#! /bin/bash + +date=$(date --rfc-3339=date) +title= +author= + +function input { + echo "Enter post title:" + read title + echo "Enter author name:" + read author +} + +function confirmation { + echo "Is the following correct?" + echo "title: $title" + echo "author: $author" + echo "y/n" +} + +function main { + local conf="n" + while [ "$conf" != "y" ] + do + input + confirmation + read conf + done + postname="./site/posts/$date-${title// /-}.md" + echo -e "---\ntitle: ${title}\nauthor: ${author}\ndescription: \n---" >> $postname + vim $postname +} + +main + +unset date title author diff --git a/site/about.md b/site/about.md new file mode 100644 index 0000000..9fe3afe --- /dev/null +++ b/site/about.md @@ -0,0 +1,12 @@ +--- +title: About +--- + +ChaosZone is the project to setting up an collaborative Assembly at the 34th +Chaos Communication Congress. + +ChaosZone wants to becaome a place - a platform - to unite hackspaces around +C3D2, the Erfa of the Chaos Computer Club from Dresden in the former GDR. + +We are focused on hacking (software, hardware and other stuff). We are +providing a friendly environment for learning from each other. diff --git a/site/contact.md b/site/contact.md new file mode 100644 index 0000000..d4ab3f5 --- /dev/null +++ b/site/contact.md @@ -0,0 +1,8 @@ +--- +title: Contact +--- + +If you wish to contact the people behind the planned assembly, you may write to +. + +To contact the administrator of this site, write to . diff --git a/site/css/default.css b/site/css/default.css new file mode 100644 index 0000000..18ea215 --- /dev/null +++ b/site/css/default.css @@ -0,0 +1,142 @@ +body { + color: white; + background-color: black; + background-image: linear-gradient(to bottom, rgba(0,0,0,0.9) 0%,rgba(0,0,0,0.9) 100%), url(/images/Chaoszone.svg); + background-size: contain; + background-attachment:fixed; + background-repeat:no-repeat; + background-position: center; + font-family: 'Xolonium'; + font-size: 16px; + font-weight: normal; + font-style: normal; + margin: 0 50px 0; + display: flex; + min-height: 100vh; + flex-direction: column; +} + +header { + border-bottom: 2px solid white; + margin-bottom: 30px; + padding: 12px 0px 12px 0px; +} + +a { + color: #ccc000; + text-decoration: none; +} + +a:hover { + color: #34c300; + text-decoration: underline +} + +div#logo a { + color: white; + /*float: left;*/ + font-size: 18px; + font-weight: bold; + text-decoration: none; +} + +nav { + position: relative; + float: left; +} + +nav ul{ + text-align: left; + list-style: none; + display: inline-block; + margin: 0; +} + +nav li a { + color: white; + font-size: 18px; + font-weight: bold; + margin-left: 12px; + text-decoration: none; + text-transform: uppercase; +} + +article { + margin-left: 200px; +} + +footer { + border-top: solid 2px white; + color: #555; + font-size: 12px; + margin-top: 30px; + padding: 12px 0px 12px 0px; + text-align: right; +} + +h1 { + font-size: 24px; +} + +h2 { + font-size: 20px; +} + +div.info { + color: #555; + font-size: 14px; + font-style: italic; +} + +.pagination { + display: inline-block; + width: 100% +} + +.wrapper { + flex: 1; +} + +.left, .right { + display: inline-block; + fill: curentColor; +} + +.left { + float: left; + margin-left: 10%; +} + +.right { + float: right; + margin-right: 10%; +} + +.left svg, .right svg { + margin-bottom: -3px; + margin-left: 0.8ex; + margin-right: 0.8ex; +} + +#yacs { + width: 100% +} + +.page img { + width: 100% +} + +.authors_comments { + border: 1px solid white; + border-radius: 5px; + padding: 0 1em 0; + background-color: #454545; + box-shadow: 5px 5px 5px #ffffff; + margin: 2em 0 2em; +} + +@media screen and (max-width: 600px){ + article { + margin: 120px 0 0 0; + } +} diff --git a/site/css/font.css b/site/css/font.css new file mode 100644 index 0000000..8d75282 --- /dev/null +++ b/site/css/font.css @@ -0,0 +1,6 @@ +@font-face { + font-family: 'Xolonium' + src: url('/fonts/Xolononiu-Regular.otf') format('opentype'); + font-weight: normal; + font-style: normal; +} diff --git a/site/css/hover.scss b/site/css/hover.scss new file mode 100644 index 0000000..3334e30 --- /dev/null +++ b/site/css/hover.scss @@ -0,0 +1,56 @@ +.tooltip-toggle { + cursor: pointer; + //position: relative; + + //Tooltip text container + &::before { + position: absolute; + top: -30px; + //left: -80px; + background-color: #00ff00; + border-radius: 5px; + color: #fff; + content: attr(aria-label); //This pulls in the text from the element with the tooltip + padding: 1ex; + text-transform: none; + font-weight: bold; + transition: all 0.5s ease; + width: 160px; + line-height: 16px; + } + + //Tooltip arrow + //&::after { + // position: absolute; + // top: -12px; + // left: 9px; + // border-left: 5px solid transparent; + // border-right: 5px solid transparent; + // border-top: 5px solid #2B222A; + // content: " "; + // font-size: 0; + // line-height: 0; + // margin-left: -5px; + // width: 0; + //} + + //Setting up the transition + &::before, + &::after { + color: #efefef; + font-family: monospace; + font-size: 16px; + opacity: 0; + pointer-events: none; + text-align: center; + } + + //Triggering the transition + &:focus::before, + &:focus::after, + &:hover::before, + &:hover::after { + opacity: 1; + transition: all 0.75s ease; + } +} diff --git a/site/css/math.scss b/site/css/math.scss new file mode 100644 index 0000000..c48a081 --- /dev/null +++ b/site/css/math.scss @@ -0,0 +1,58 @@ +@function fact($number) { + $value: 1; + @if $number > 0 { + @for $i from 1 through $number { + $value: $value * $i; + } + } + @return $value; +} + +@function pow($number, $exp) { + $value: 1; + @if $exp > 0 { + @for $i from 1 through $exp { + $value: $value * $number; + } + } + @else if $exp < 0 { + @for $i from 1 through -$exp { + $value: $value / $number; + } + } + @return $value; +} + +@function pi() { + @return 3.14159265359; +} + +@function rad($angle) { + $unit: unit($angle); + $unitless: $angle / ($angle * 0 + 1); + // If the angle has 'deg' as unit, convert to radians. + @if $unit == deg { + $unitless: $unitless / 180 * pi(); + } + @return $unitless; +} + +@function sin($angle) { + $sin: 0; + $angle: rad($angle); + // Iterate a bunch of times. + @for $i from 0 through 10 { + $sin: $sin + pow(-1, $i) * pow($angle, (2 * $i + 1)) / fact(2 * $i + 1); + } + @return $sin; +} + +@function cos($angle) { + $cos: 0; + $angle: rad($angle); + // Iterate a bunch of times. + @for $i from 0 through 10 { + $cos: $cos + pow(-1, $i) * pow($angle, 2 * $i) / fact(2 * $i); + } + @return $cos; +} diff --git a/site/css/menu.scss b/site/css/menu.scss new file mode 100644 index 0000000..26fd814 --- /dev/null +++ b/site/css/menu.scss @@ -0,0 +1,183 @@ +@import "math"; + +// vars +$fg:#ff0000; +$bg:#00ff00; + +// config +$menu-items: 5; +$open-distance: 110px; +$start-angle: (0 - pi()) / 2; +$opening-angle: pi() + 0; + +.menu { + //@extend %goo; + $width:300px; + $height:300px; + //$width: 250px + (150px * abs(cos($start-angle))); + //$height: 250px + (150px * abs(sin($start-angle))); + position:fixed; + //left:50%; + display: inline-block; + margin-left:-$width/2; + padding-top:$height/2; + padding-left:$width/2; + padding-bottom:-$height/2; + width:$width; + height:$height; + box-sizing:border-box; + font-size:20px; + text-align:left; +} + +%ball { + background: $bg; + border-radius: 50%; + width: 80px; + height: 80px; + margin-left: -40px; + margin-top: -40px; + position: absolute; + top: 50%; + color: white; + text-align:center; + line-height: 80px; + transform: translate3d(0,0,0); + transition:transform ease-out 200ms; + + svg { + padding-top: 10px; + width: 60px; + height: 60px; + } +} + +.menu-open { + display: none; +} + +.menu-item { + @extend %ball; +} + +.hamburger { + $width: 25px; + $height: 3px; + width: $width; + height: $height; + background: white; + display: block; + position: absolute; + top: 50%; + left: 50%; + margin-left: -$width/2; + margin-top: -$height/2; + transition: transform 200ms; +} + +$hamburger-spacing:8px; + +.hamburger-1 { + transform:translate3d(0,-$hamburger-spacing,0); +} + +.hamburger-2 { + transform:translate3d(0,0,0); +} + +.hamburger-3 { + transform:translate3d(0,$hamburger-spacing,0); +} + +.menu-open:checked + .menu-open-button { + .hamburger-1 { + transform:translate3d(0,0,0) rotate(45deg); + } + + .hamburger-2 { + transform:translate3d(0,0,0) scale(0.1,1); + } + + .hamburger-3 { + transform:translate3d(0,0,0) rotate(-45deg); + } +} + +.menu-item { + &:hover { + background:#acffac; + color:$fg; + } + @for $i from 1 through $menu-items { + &:nth-child(#{$i+2}) { + transition-duration:10ms+(60ms*($i)); + } + } +} + +.menu-open-button { + @extend %ball; + z-index:2; + //transition-timing-function:cubic-bezier(0.175, 0.885, 0.320, 1.275); + transition-timing-function:cubic-bezier(0.175, 0.885, 0.320, 1.0); + transition-duration:400ms; + transform:scale(1.1,1.1) translate3d(0,0,0); + cursor:pointer; +} + +.menu-open-button:hover { + transform:scale(1.2,1.2) translate3d(0,0,0); +} + +.menu-open:checked + .menu-open-button { + transition-timing-function:linear; + transition-duration:200ms; + transform:scale(0.8,0.8) translate3d(0,0,0); +} + +.menu-open:checked ~ .menu-item { + transition-timing-function:cubic-bezier(0.935, 0.000, 0.340, 1.330); + @for $i from 1 through $menu-items { + $angle:((pi() - pi())/2)+((pi()/($menu-items - 1))*($i - 1) + $start-angle); + + &:nth-child(#{$i+2}) { + transition-duration:80ms+(80ms*$i); + transform:translate3d(cos($angle)*$open-distance,sin($angle)*$open-distance,0); + } + } +} + +@media screen and (max-width: 600px){ + .menu { + position: relative; + padding-top: 0; + padding-bottom: 0; + height: 80px; + width: 100%; + } + + %ball { + $dim: 1.4cm; + width: $dim; + height: $dim; + line-height: $dim; + + svg { + $dim: 1.2cm; + padding-top: 0.1cm; + width: $dim; + height: $dim; + } + } + + + .menu-open:checked~.menu-item{ + transition-timing-function:cubic-bezier(0.165, 0.840, 0.440, 1.000); + @for $i from 1 through $menu-items{ + &:nth-child(#{$i+2}){ + transition-duration:90ms+(100ms*$i); + transform:translate3d(1.4cm*$i,0,0); + } + } + } +} diff --git a/site/fonts/Xolonium-Regular.otf b/site/fonts/Xolonium-Regular.otf new file mode 100644 index 0000000..cf31485 Binary files /dev/null and b/site/fonts/Xolonium-Regular.otf differ diff --git a/site/images/Chaoszone.png b/site/images/Chaoszone.png new file mode 100644 index 0000000..4e5b949 Binary files /dev/null and b/site/images/Chaoszone.png differ diff --git a/site/images/Chaoszone.svg b/site/images/Chaoszone.svg new file mode 100644 index 0000000..e7aa5d3 --- /dev/null +++ b/site/images/Chaoszone.svg @@ -0,0 +1,35 @@ + + + + + + + image/svg+xml + + + + + + + + + diff --git a/site/images/haskell-logo.png b/site/images/haskell-logo.png new file mode 100644 index 0000000..97c0937 Binary files /dev/null and b/site/images/haskell-logo.png differ diff --git a/site/index.md b/site/index.md new file mode 100644 index 0000000..6251f25 --- /dev/null +++ b/site/index.md @@ -0,0 +1,17 @@ +--- +title: Home +--- + +## Welcome, Comrades! + + +Welcome to this blog! + +We are ChaosZone, mostly hackers from eastern countries, but all creatures are +welcome. Meet us at our Assembly at 34C3. + +The latest posts here are + +$partial("templates/post-list.html")$ + +…and there are even more in the [archive](/archive.html). diff --git a/site/personae/neil.kra b/site/personae/neil.kra new file mode 100644 index 0000000..20fe7bf Binary files /dev/null and b/site/personae/neil.kra differ diff --git a/site/personae/neil.kra~ b/site/personae/neil.kra~ new file mode 100644 index 0000000..3ad3054 Binary files /dev/null and b/site/personae/neil.kra~ differ diff --git a/site/posts/2017-11-09-Hello-World!.md b/site/posts/2017-11-09-Hello-World!.md new file mode 100644 index 0000000..832c2c6 --- /dev/null +++ b/site/posts/2017-11-09-Hello-World!.md @@ -0,0 +1,13 @@ +--- +title: Hello World! +author: nek0 +description: The ChaosZone introduces itself +--- + +Hi there! + +We are the ChaosZone, an assembly of hackers from eastern countries at the 34th +Chaos Communication Congress in Leipzig. + +We aim to provide a comfy coding space with lots of collaboration, information +and knowledge sharing. diff --git a/src/Main.hs b/src/Main.hs new file mode 100644 index 0000000..c5d53f5 --- /dev/null +++ b/src/Main.hs @@ -0,0 +1,154 @@ +-------------------------------------------------------------------------------- +{-# LANGUAGE OverloadedStrings #-} +import Data.Monoid ((<>)) +import Hakyll +-- import Hakyll.Web.Sass + +import Data.Time.Clock (UTCTime) +import Data.Time.Format (parseTimeM, defaultTimeLocale) +import Data.List +import Data.Maybe (fromMaybe) +import System.FilePath (takeFileName) +import Control.Monad (liftM) +import Network.HTTP.Base (urlEncode) + +-------------------------------------------------------------------------------- + +baseUrl :: String +baseUrl = "https://chaoszone.cz" + +main :: IO () +main = hakyllWith config $ do + + is <- sortIdentifiersByDate <$> getMatches "site/posts/*.md" + + match "templates/*" $ compile templateBodyCompiler + + match + ( "site/images/*" + .||. "site/fonts/*" + .||. "site/humans.txt" + .||. "site/robots.txt" + ) $ do + route myRoute + compile copyFileCompiler + + match "site/css/*.css" $ do + route myRoute + compile compressCssCompiler + + -- match "site/css/*.scss" $ do + -- route $ myRoute `composeRoutes` setExtension "css" + -- compile $ fmap compressCss <$> sassCompiler + + match (fromList ["site/about.md", "site/contact.md"]) $ do + route $ myRoute `composeRoutes` setExtension "html" + compile $ do + -- firstUrl <- return . fromMaybe "" =<< getRoute (head is) + -- latestUrl <- return . fromMaybe "" =<< getRoute (last is) + pandocCompiler + >>= loadAndApplyTemplate "templates/default.html" + -- (menuCtx firstUrl latestUrl) + defaultContext + >>= relativizeUrls + + match "site/index.md" $ do + route $ myRoute `composeRoutes` setExtension "html" + compile $ do + posts <- fmap (take 5) . recentFirst =<< loadAll "site/posts/*" + let indexCtx = listField "posts" postCtx (return posts) <> + constField "title" "Home" <> + defaultContext + getResourceBody + >>= applyAsTemplate indexCtx + >>= renderPandoc + >>= loadAndApplyTemplate "templates/default.html" defaultContext + >>= relativizeUrls + + create ["archive.html"] $ do + route idRoute + compile $ do + -- firstUrl <- return . fromMaybe "" =<< getRoute (head is) + -- latestUrl <- return . fromMaybe "" =<< getRoute (last is) + posts <- recentFirst =<< loadAll "site/posts/*" + let archiveCtx = + listField "posts" postCtx (return posts) <> + constField "title" "Archives" <> + -- (menuCtx firstUrl latestUrl) + defaultContext + makeItem "" + >>= loadAndApplyTemplate "templates/archive.html" archiveCtx + >>= loadAndApplyTemplate "templates/default.html" archiveCtx + >>= relativizeUrls + + pages <- buildPaginateWith + (liftM (paginateEvery 1) . sortRecentFirst) + "site/posts/*.md" + (\n -> is !! (n - 1)) + + paginateRules pages $ \num pat -> do + route $ myRoute `composeRoutes` setExtension "html" + compile $ do + -- firstUrl <- fmap ('/' :) . return . fromMaybe "" =<< getRoute (head is) + -- latestUrl <- fmap ('/' :) . return . fromMaybe "" =<< getRoute (last is) + ident <- getUnderlying + title <- getMetadataField' ident "title" + url <- return . fromMaybe "" =<< getRoute ident + compiled <- getResourceBody >>= renderPandoc + let pageCtx = paginateContext pages num + let flattrCtx = constField "enctitle" (urlEncode title) <> + constField "encurl" (urlEncode $ baseUrl ++ url) + let ctx = postCtx <> pageCtx <> flattrCtx + full <- loadAndApplyTemplate "templates/post.html" ctx compiled + _ <- saveSnapshot "content" compiled + loadAndApplyTemplate "templates/default.html" + defaultContext full + >>= relativizeUrls + + -- create ["index.html"] $ do + -- route idRoute + -- compile $ do + -- post <- fmap head . recentFirst =<< (loadAll "site/posts/*" :: Compiler [Item String]) + -- let indexCtx = + -- constField "date" "%B %e, %Y" <> + -- defaultContext + -- makeItem (itemBody post) + -- >>= relativizeUrls + +-------------------------------------------------------------------------------- + +myRoute :: Routes +myRoute = gsubRoute "site/" (const "") + +-------------------------------------------------------------------------------- +postCtx :: Context String +postCtx = + dateField "date" "%B %e, %Y" <> + defaultContext + +-- menuCtx :: String -> String -> Context String +-- menuCtx first latest = +-- constField "first" first <> +-- constField "latest" latest <> +-- defaultContext + +-------------------------------------------------------------------------------- +config :: Configuration +config = defaultConfiguration + { deployCommand = "rsync --del --checksum -rave 'ssh -p 5555' _site/* nek0@chelnok.de:/home/nek0/www/chaoszone" + } + +-------------------------------------------------------------------------------- + +sortIdentifiersByDate :: [Identifier] -> [Identifier] +sortIdentifiersByDate = + sortBy byDate + where + byDate id1 id2 = + let fn1 = takeFileName $ toFilePath id1 + fn2 = takeFileName $ toFilePath id2 + parseTime' fn = parseTimeM True defaultTimeLocale "%Y-%m-%d" $ + intercalate "-" $ take 3 $ splitAll "-" fn + in compare + (parseTime' fn1 :: Maybe UTCTime) + (parseTime' fn2 :: Maybe UTCTime) diff --git a/templates/archive.html b/templates/archive.html new file mode 100644 index 0000000..b43eeb2 --- /dev/null +++ b/templates/archive.html @@ -0,0 +1,2 @@ +Here you can find all my previous posts: +$partial("templates/post-list.html")$ diff --git a/templates/default.html b/templates/default.html new file mode 100644 index 0000000..c3fb1b9 --- /dev/null +++ b/templates/default.html @@ -0,0 +1,40 @@ + + + + + + + ChaosZone + + + + + +
+ + + + +
+

$title$

+ $body$ +
+
+ +
+ Site proudly generated by + Hakyll +
+ + diff --git a/templates/post-list.html b/templates/post-list.html new file mode 100644 index 0000000..995c6a1 --- /dev/null +++ b/templates/post-list.html @@ -0,0 +1,7 @@ +
    +$for(posts)$ +
  • +$title$ - $date$ +
  • +$endfor$ +
diff --git a/templates/post.html b/templates/post.html new file mode 100644 index 0000000..d65d224 --- /dev/null +++ b/templates/post.html @@ -0,0 +1,17 @@ +
+ Posted on $date$ + $if(author)$ + by $author$ + $endif$ +
+ +$body$ + +