diff --git a/README.md b/README.md index ae6822a..a6003ee 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![wercker status](https://app.wercker.com/status/389477226e537a45143ea91336dca281/m "wercker status")](https://app.wercker.com/project/bykey/389477226e537a45143ea91336dca281) +[![wercker status](https://app.wercker.com/status/8d96ab89960da21d87a545a25acae54c/m/master "wercker status")](https://app.wercker.com/project/byKey/8d96ab89960da21d87a545a25acae54c) This repo contains the sources for the Nim by Example book. diff --git a/Rules b/Rules index e2b5ac4..b0d6960 100644 --- a/Rules +++ b/Rules @@ -13,35 +13,59 @@ # item, use the pattern “/about/*/”; “/about/*” will also select the parent, # because “*” matches zero or more characters. -compile '*' do - if item.identifier == '/toc/' +compile '/assets/css/*' do + filter :erb + filter :rainpress if File.basename(item[:content_filename], ".*") == 'all' +end + +compile '/assets/js/*' do + filter :erb + :uglify_js if File.basename(item[:content_filename], ".*") == 'all' +end + +compile '/content/*' do + if item.identifier.to_s == '/content/toc/' filter :kramdown layout 'blank' + elsif item.identifier.to_s == '/content/footer/' + layout 'blank' elsif item[:extension] == 'md' filter :kramdown, {:input => 'GFM'} filter :colorize_syntax, :default_colorizer => :pygmentize filter :relativize_paths, :type => :html layout 'default' - elsif item[:extension] == 'css' - # don’t filter stylesheets - elsif item.binary? - # don’t filter binary items else filter :erb layout 'default' end end -route '*' do - if item[:extension] == 'css' - # Write item with identifier /foo/ to /foo.css - item.identifier.chop + '.css' - elsif item.binary? +route '/assets/css/*' do + # if not debug mode, only let all.css through + unless @config[:debug] + item.identifier.to_s.chop + '.css' if File.basename(item[:content_filename], ".*") == 'all' + else + item.identifier.to_s.chop + '.css' + end +end + +route '/assets/js/*' do + # if not debug mode, only let all.js through + unless @config[:debug] + item.identifier.to_s.chop + '.js' if File.basename(item[:content_filename], ".*") == 'all' + else + item.identifier.to_s.chop + '.js' + end +end + + +route '/content/*' do + if item.binary? # Write item with identifier /foo/ to /foo.ext - item.identifier.chop + '.' + item[:extension] + item.identifier.to_s.sub("/content", "").chop + '.' + item[:extension] else # Write item with identifier /foo/ to /foo/index.html - item.identifier + 'index.html' + item.identifier.to_s.sub("/content", "") + 'index.html' end end diff --git a/content/assets/css/all.css b/content/assets/css/all.css new file mode 100644 index 0000000..f385aa0 --- /dev/null +++ b/content/assets/css/all.css @@ -0,0 +1 @@ +<%= all_css @config[:stylesheets] %> diff --git a/content/assets/css/colorful.css b/content/assets/css/colorful.css new file mode 100644 index 0000000..d29370e --- /dev/null +++ b/content/assets/css/colorful.css @@ -0,0 +1,72 @@ +/* pygments-css colorful */ +code[class^='language-'] .gp { + color: #c65d09; + font-weight: bold; + /* NOTE: Hacks to allow copy-paste */ + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} /* Generic.Prompt */ +body:not(.darkmode) code[class^='language-'] .hll { background-color: #ffffcc } +body:not(.darkmode) code[class^='language-'] .c { color: #808080 } /* Comment */ +body:not(.darkmode) code[class^='language-'] .err { color: #F00000; background-color: #F0A0A0 } /* Error */ +body:not(.darkmode) code[class^='language-'] .k { color: #008000; font-weight: bold } /* Keyword */ +body:not(.darkmode) code[class^='language-'] .o { color: #303030 } /* Operator */ +body:not(.darkmode) code[class^='language-'] .cm { color: #808080 } /* Comment.Multiline */ +body:not(.darkmode) code[class^='language-'] .cp { color: #507090 } /* Comment.Preproc */ +body:not(.darkmode) code[class^='language-'] .c1 { color: #808080 } /* Comment.Single */ +body:not(.darkmode) code[class^='language-'] .cs { color: #cc0000; font-weight: bold } /* Comment.Special */ +body:not(.darkmode) code[class^='language-'] .gd { color: #A00000 } /* Generic.Deleted */ +body:not(.darkmode) code[class^='language-'] .ge { font-style: italic } /* Generic.Emph */ +body:not(.darkmode) code[class^='language-'] .gr { color: #FF0000 } /* Generic.Error */ +body:not(.darkmode) code[class^='language-'] .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +body:not(.darkmode) code[class^='language-'] .gi { color: #00A000 } /* Generic.Inserted */ +body:not(.darkmode) code[class^='language-'] .go { color: #808080 } /* Generic.Output */ +body:not(.darkmode) code[class^='language-'] .gs { font-weight: bold } /* Generic.Strong */ +body:not(.darkmode) code[class^='language-'] .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +body:not(.darkmode) code[class^='language-'] .gt { color: #0040D0 } /* Generic.Traceback */ +body:not(.darkmode) code[class^='language-'] .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +body:not(.darkmode) code[class^='language-'] .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +body:not(.darkmode) code[class^='language-'] .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +body:not(.darkmode) code[class^='language-'] .kp { color: #003080; font-weight: bold } /* Keyword.Pseudo */ +body:not(.darkmode) code[class^='language-'] .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +body:not(.darkmode) code[class^='language-'] .kt { color: #303090; font-weight: bold } /* Keyword.Type */ +body:not(.darkmode) code[class^='language-'] .m { color: #6000E0; font-weight: bold } /* Literal.Number */ +body:not(.darkmode) code[class^='language-'] .s { background-color: #fff0f0 } /* Literal.String */ +body:not(.darkmode) code[class^='language-'] .na { color: #0000C0 } /* Name.Attribute */ +body:not(.darkmode) code[class^='language-'] .nb { color: #007020 } /* Name.Builtin */ +body:not(.darkmode) code[class^='language-'] .nc { color: #B00060; font-weight: bold } /* Name.Class */ +body:not(.darkmode) code[class^='language-'] .no { color: #003060; font-weight: bold } /* Name.Constant */ +body:not(.darkmode) code[class^='language-'] .nd { color: #505050; font-weight: bold } /* Name.Decorator */ +body:not(.darkmode) code[class^='language-'] .ni { color: #800000; font-weight: bold } /* Name.Entity */ +body:not(.darkmode) code[class^='language-'] .ne { color: #F00000; font-weight: bold } /* Name.Exception */ +body:not(.darkmode) code[class^='language-'] .nf { color: #0060B0; font-weight: bold } /* Name.Function */ +body:not(.darkmode) code[class^='language-'] .nl { color: #907000; font-weight: bold } /* Name.Label */ +body:not(.darkmode) code[class^='language-'] .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +body:not(.darkmode) code[class^='language-'] .nt { color: #007000 } /* Name.Tag */ +body:not(.darkmode) code[class^='language-'] .nv { color: #906030 } /* Name.Variable */ +body:not(.darkmode) code[class^='language-'] .ow { color: #000000; font-weight: bold } /* Operator.Word */ +body:not(.darkmode) code[class^='language-'] .w { color: #bbbbbb } /* Text.Whitespace */ +body:not(.darkmode) code[class^='language-'] .mf { color: #6000E0; font-weight: bold } /* Literal.Number.Float */ +body:not(.darkmode) code[class^='language-'] .mh { color: #005080; font-weight: bold } /* Literal.Number.Hex */ +body:not(.darkmode) code[class^='language-'] .mi { color: #0000D0; font-weight: bold } /* Literal.Number.Integer */ +body:not(.darkmode) code[class^='language-'] .mo { color: #4000E0; font-weight: bold } /* Literal.Number.Oct */ +body:not(.darkmode) code[class^='language-'] .sb { background-color: #fff0f0 } /* Literal.String.Backtick */ +body:not(.darkmode) code[class^='language-'] .sc { color: #0040D0 } /* Literal.String.Char */ +body:not(.darkmode) code[class^='language-'] .sd { color: #D04020 } /* Literal.String.Doc */ +body:not(.darkmode) code[class^='language-'] .s2 { background-color: #fff0f0 } /* Literal.String.Double */ +body:not(.darkmode) code[class^='language-'] .se { color: #606060; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */ +body:not(.darkmode) code[class^='language-'] .sh { background-color: #fff0f0 } /* Literal.String.Heredoc */ +body:not(.darkmode) code[class^='language-'] .si { background-color: #e0e0e0 } /* Literal.String.Interpol */ +body:not(.darkmode) code[class^='language-'] .sx { color: #D02000; background-color: #fff0f0 } /* Literal.String.Other */ +body:not(.darkmode) code[class^='language-'] .sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */ +body:not(.darkmode) code[class^='language-'] .s1 { background-color: #fff0f0 } /* Literal.String.Single */ +body:not(.darkmode) code[class^='language-'] .ss { color: #A06000 } /* Literal.String.Symbol */ +body:not(.darkmode) code[class^='language-'] .bp { color: #007020 } /* Name.Builtin.Pseudo */ +body:not(.darkmode) code[class^='language-'] .vc { color: #306090 } /* Name.Variable.Class */ +body:not(.darkmode) code[class^='language-'] .vg { color: #d07000; font-weight: bold } /* Name.Variable.Global */ +body:not(.darkmode) code[class^='language-'] .vi { color: #3030B0 } /* Name.Variable.Instance */ +body:not(.darkmode) code[class^='language-'] .il { color: #0000D0; font-weight: bold } /* Literal.Number.Integer.Long */ diff --git a/content/assets/css/cotton_candy.css b/content/assets/css/cotton_candy.css new file mode 100644 index 0000000..ef6d896 --- /dev/null +++ b/content/assets/css/cotton_candy.css @@ -0,0 +1,8 @@ +#main code, code * { color: #675D69; } +code[class^='language-'] .k { color: #143A77; } +code[class^='language-'] .kp { color: #8C5DC7; } +code[class^='language-'] .kd { color: #8C5DC7; } +code[class^='language-'] .mi { color: #8C5DC7; } +code[class^='language-'] .s { color: #0060B0; } +code[class^='language-'] .c { color: #91B9A3; } +code[class^='language-'] .o { color: #009DE7; } diff --git a/content/assets/css/main.css b/content/assets/css/main.css new file mode 100644 index 0000000..8d14e3e --- /dev/null +++ b/content/assets/css/main.css @@ -0,0 +1,133 @@ +body { + background: #F5F7F6; + color: #000000; + margin: 0; padding: 0; + max-width: 720px; + + text-rendering: optimizelegibility; + + font-family: Palatino, serif; + line-height: 20px; +} + +#sidebar { + margin: 15px; + float: left; + width: 205px; + padding: 10px 0; + + background-color: #FFF; + box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.5); + + transition: margin-left 1s; +} + +#sidebar.collapsed { margin-left: -180px; } + +#sidebar ul { padding: 0 1em; margin: 0; list-style-type: none; } +#sidebar li:before { content: '⁃'; padding-right: 0.5em; color: black; } +#sidebar li.visited:before { content: '✔'; padding-right: 0.2em; color: green; } + + +.abs-hamburger { + position: relative; + width: 0; height: 0; +} +.nav-toggle { + position: absolute; + left: 175px; + width: 25px; height: 25px; + cursor: pointer; + margin-right: 5px; + margin-bottom: 5px; +} +.nav-toggle span, +.nav-toggle span:before, +.nav-toggle span:after { + border-radius: 1px; + height: 5px; + width: 25px; + background: white; + position: absolute; + display: block; + content: ''; + box-shadow: inset 0px 0px 2px 0px #000; +} +.nav-toggle span:before { top: -8px; } +.nav-toggle span:after { bottom: -8px; } +.nav-toggle span { margin-top: 9.5px; } + + +#nextprev { + overflow: hidden; + padding: .5em 1em; +} + +.text-icon { font-size: 5em; } +#arrow-prev { float: left; } +#arrow-next { float: right; } + + +article { + margin: 15px; + + transition: max-width 1s; +} +article.expanded { max-width: 680px; } + + +a { text-decoration: none; } +a:link, a:visited { color: #B45D47; } +a:hover { color: #FE3B3B; } + +a.disabled, a:link.disabled, a:visited.disabled { color: #999; pointer-events: none; } +a:hover.disabled { color: #888; } + + +pre, code { font-family: Monaco, Menlo, Consolas, "Courier New", monospace; } +code { + border-radius: 1px; + background-color: #FFF; + padding: 0.2em; +} +pre code { + display: block; + padding: 1em; + white-space: pre-wrap; +} + + +h1, h2, h3, h4, h5, h6 { line-height: 125%; } + + +footer { + margin-top: 50px; + clear: both; + + text-align: center; + color: #777; +} +footer ul { list-style: none; margin: 0; padding: 0; } +footer li { display: inline; } +footer li+li:before { content: '|'; } +footer a:link, footer a:visited { color: #777; } +footer a:hover { color: #999; } + +.notransition { + -webkit-transition: none !important; + -moz-transition: none !important; + -o-transition: none !important; + -ms-transition: none !important; + transition: none !important; +} + + +@media screen and (min-width: 925px) { + body { margin: 0 auto; } + body #sidebar.collapsed, body #sidebar { margin-left: -205px; } + body article.expanded, body article { max-width: none; width: none; min-width: none; } +} + +@media screen and (max-width: 1200px) { + body { margin-right: 0; } +} diff --git a/content/assets/css/monokai.css b/content/assets/css/monokai.css new file mode 100644 index 0000000..3dcebc7 --- /dev/null +++ b/content/assets/css/monokai.css @@ -0,0 +1,64 @@ +body.darkmode code[class^='language-'] { background-color: #333; color: #f8f8f2} +body.darkmode code[class^='language-'] .hll { background-color: #49483e } +body.darkmode code[class^='language-'] .c { color: #75715e } /* Comment */ +body.darkmode code[class^='language-'] .err { color: #960050; background-color: #1e0010 } /* Error */ +body.darkmode code[class^='language-'] .k { color: #66d9ef } /* Keyword */ +body.darkmode code[class^='language-'] .l { color: #ae81ff } /* Literal */ +body.darkmode code[class^='language-'] .n { color: #f8f8f2 } /* Name */ +body.darkmode code[class^='language-'] .o { color: #f92672 } /* Operator */ +body.darkmode code[class^='language-'] .p { color: #f8f8f2 } /* Punctuation */ +body.darkmode code[class^='language-'] .cm { color: #75715e } /* Comment.Multiline */ +body.darkmode code[class^='language-'] .cp { color: #75715e } /* Comment.Preproc */ +body.darkmode code[class^='language-'] .c1 { color: #75715e } /* Comment.Single */ +body.darkmode code[class^='language-'] .cs { color: #75715e } /* Comment.Special */ +body.darkmode code[class^='language-'] .ge { font-style: italic } /* Generic.Emph */ +body.darkmode code[class^='language-'] .gs { font-weight: bold } /* Generic.Strong */ +body.darkmode code[class^='language-'] .kc { color: #66d9ef } /* Keyword.Constant */ +body.darkmode code[class^='language-'] .kd { color: #66d9ef } /* Keyword.Declaration */ +body.darkmode code[class^='language-'] .kn { color: #f92672 } /* Keyword.Namespace */ +body.darkmode code[class^='language-'] .kp { color: #66d9ef } /* Keyword.Pseudo */ +body.darkmode code[class^='language-'] .kr { color: #66d9ef } /* Keyword.Reserved */ +body.darkmode code[class^='language-'] .kt { color: #66d9ef } /* Keyword.Type */ +body.darkmode code[class^='language-'] .ld { color: #e6db74 } /* Literal.Date */ +body.darkmode code[class^='language-'] .m { color: #ae81ff } /* Literal.Number */ +body.darkmode code[class^='language-'] .s { color: #e6db74 } /* Literal.String */ +body.darkmode code[class^='language-'] .na { color: #a6e22e } /* Name.Attribute */ +body.darkmode code[class^='language-'] .nb { color: #f8f8f2 } /* Name.Builtin */ +body.darkmode code[class^='language-'] .nc { color: #a6e22e } /* Name.Class */ +body.darkmode code[class^='language-'] .no { color: #66d9ef } /* Name.Constant */ +body.darkmode code[class^='language-'] .nd { color: #a6e22e } /* Name.Decorator */ +body.darkmode code[class^='language-'] .ni { color: #f8f8f2 } /* Name.Entity */ +body.darkmode code[class^='language-'] .ne { color: #a6e22e } /* Name.Exception */ +body.darkmode code[class^='language-'] .nf { color: #a6e22e } /* Name.Function */ +body.darkmode code[class^='language-'] .nl { color: #f8f8f2 } /* Name.Label */ +body.darkmode code[class^='language-'] .nn { color: #f8f8f2 } /* Name.Namespace */ +body.darkmode code[class^='language-'] .nx { color: #a6e22e } /* Name.Other */ +body.darkmode code[class^='language-'] .py { color: #f8f8f2 } /* Name.Property */ +body.darkmode code[class^='language-'] .nt { color: #f92672 } /* Name.Tag */ +body.darkmode code[class^='language-'] .nv { color: #f8f8f2 } /* Name.Variable */ +body.darkmode code[class^='language-'] .ow { color: #f92672 } /* Operator.Word */ +body.darkmode code[class^='language-'] .w { color: #f8f8f2 } /* Text.Whitespace */ +body.darkmode code[class^='language-'] .mf { color: #ae81ff } /* Literal.Number.Float */ +body.darkmode code[class^='language-'] .mh { color: #ae81ff } /* Literal.Number.Hex */ +body.darkmode code[class^='language-'] .mi { color: #ae81ff } /* Literal.Number.Integer */ +body.darkmode code[class^='language-'] .mo { color: #ae81ff } /* Literal.Number.Oct */ +body.darkmode code[class^='language-'] .sb { color: #e6db74 } /* Literal.String.Backtick */ +body.darkmode code[class^='language-'] .sc { color: #e6db74 } /* Literal.String.Char */ +body.darkmode code[class^='language-'] .sd { color: #e6db74 } /* Literal.String.Doc */ +body.darkmode code[class^='language-'] .s2 { color: #e6db74 } /* Literal.String.Double */ +body.darkmode code[class^='language-'] .se { color: #ae81ff } /* Literal.String.Escape */ +body.darkmode code[class^='language-'] .sh { color: #e6db74 } /* Literal.String.Heredoc */ +body.darkmode code[class^='language-'] .si { color: #e6db74 } /* Literal.String.Interpol */ +body.darkmode code[class^='language-'] .sx { color: #e6db74 } /* Literal.String.Other */ +body.darkmode code[class^='language-'] .sr { color: #e6db74 } /* Literal.String.Regex */ +body.darkmode code[class^='language-'] .s1 { color: #e6db74 } /* Literal.String.Single */ +body.darkmode code[class^='language-'] .ss { color: #e6db74 } /* Literal.String.Symbol */ +body.darkmode code[class^='language-'] .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ +body.darkmode code[class^='language-'] .vc { color: #f8f8f2 } /* Name.Variable.Class */ +body.darkmode code[class^='language-'] .vg { color: #f8f8f2 } /* Name.Variable.Global */ +body.darkmode code[class^='language-'] .vi { color: #f8f8f2 } /* Name.Variable.Instance */ +body.darkmode code[class^='language-'] .il { color: #ae81ff } /* Literal.Number.Integer.Long */ +body.darkmode code[class^='language-'] .gh { } /* Generic Heading & Diff Header */ +body.darkmode code[class^='language-'] .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */ +body.darkmode code[class^='language-'] .gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */ +body.darkmode code[class^='language-'] .gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */ diff --git a/content/assets/css/normalize.css b/content/assets/css/normalize.css new file mode 100644 index 0000000..b6a2510 --- /dev/null +++ b/content/assets/css/normalize.css @@ -0,0 +1 @@ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} diff --git a/content/assets/js/all.js b/content/assets/js/all.js new file mode 100644 index 0000000..30b2c4c --- /dev/null +++ b/content/assets/js/all.js @@ -0,0 +1 @@ +<%= all_js @config[:scripts] %> diff --git a/content/assets/js/main.js b/content/assets/js/main.js new file mode 100644 index 0000000..32f8de1 --- /dev/null +++ b/content/assets/js/main.js @@ -0,0 +1,87 @@ +function setVisibleTags(){ + var tocLinks = document.querySelectorAll("#sidebar a:link, a:visited"); + for(var i = 0; i < tocLinks.length; i++){ + if(localStorage.getItem(tocLinks[i].getAttribute("href")) != null){ + tocLinks[i].parentNode.classList.add("visited"); + } + } +} + +function updateSidebar(notransition) { + if (notransition) { + document.querySelectorAll("#sidebar")[0].classList.add("notransition"); + document.querySelectorAll("article")[0].classList.add("notransition"); + } + localStorage.setItem("openside", window.sidebarExpanded); + if (!window.sidebarExpanded) { + document.querySelectorAll("#sidebar")[0].classList.add("collapsed"); + document.querySelectorAll("article")[0].classList.add("expanded"); + } else { + document.querySelectorAll("#sidebar")[0].classList.remove("collapsed"); + document.querySelectorAll("article")[0].classList.remove("expanded"); + } + if (notransition) { + setTimeout(function(){ + document.querySelectorAll("#sidebar")[0].classList.remove("notransition"); + document.querySelectorAll("article")[0].classList.remove("notransition"); + }, 100); + } +} + +function sidebarClick() { + window.sidebarExpanded = !window.sidebarExpanded; + updateSidebar(false); +} + +function getNextPrev() { + // thanks iznogoodd from #nim @ freenode.net + var links = document.querySelectorAll('#sidebar a[href]'); + + var nav = {prev: null, next: null}; + for(var i = 0; i < links.length; i++){ + var item = links.item(i); + if(item && item.getAttribute('href') === window.location.pathname){ + nav.prev = links.item(i - 1) && links.item(i - 1).getAttribute('href'); + nav.next = links.item(i + 1) && links.item(i + 1).getAttribute('href'); + return nav; + } + } +} + +function updateNextPrevButtons() { + var nav = getNextPrev(); + + var prev = document.getElementById("arrow-prev"); + var next = document.getElementById("arrow-next"); + + if (nav.prev != null) { prev.classList.remove("disabled"); prev.href = nav.prev; } + if (nav.next != null) { next.classList.remove("disabled"); next.href = nav.next; } +} + +var darkmodeOn = (localStorage.getItem("darkmode") === "true"); +function toggleDarkMode() { + darkmodeOn = !darkmodeOn; + document.getElementsByTagName("body")[0].classList.toggle("darkmode"); + localStorage.setItem("darkmode", darkmodeOn); +} + +function initDarkMode() { + if (darkmodeOn) + document.getElementsByTagName("body")[0].classList.add("darkmode"); +} + + +var isMobile = window.screen.width < 720; +if (localStorage.getItem("openside") === null) { + window.sidebarExpanded = !isMobile; +} else { + window.sidebarExpanded = (localStorage.getItem("openside") === "true"); +} + +localStorage.setItem(window.location.pathname, true); +window.onload = function(){ + updateSidebar(true); + initDarkMode(); + setVisibleTags(); + updateNextPrevButtons(); +} diff --git a/content/arrays.md b/content/content/arrays.md similarity index 96% rename from content/arrays.md rename to content/content/arrays.md index c77329f..1411ba5 100644 --- a/content/arrays.md +++ b/content/content/arrays.md @@ -4,7 +4,7 @@ title: Arrays # Arrays -The arrays in Nim are like classic C arrays, their size is specified at compile-time and cannot given or changed at runtime. +The arrays in Nim are like classic C arrays, their size is specified at compile-time and cannot be given or changed at runtime. ``` nimrod type diff --git a/content/bitsets.md b/content/content/bitsets.md similarity index 100% rename from content/bitsets.md rename to content/content/bitsets.md diff --git a/content/block.md b/content/content/block.md similarity index 90% rename from content/block.md rename to content/content/block.md index 05e591b..b445981 100644 --- a/content/block.md +++ b/content/content/block.md @@ -6,11 +6,11 @@ title: Blocks Blocks can be introduced in two different ways: by indenting statements or with `()`s. -The first way ist to use indenting, e.g. using `if-elif-else`, `while`, `for` statements, or the `block` statement. +The first way is to use indenting, e.g. using `if-elif-else`, `while`, `for` statements, or the `block` statement. ``` nimrod if true: - echo "Nimrod is great!" + echo "Nim is great!" while false: echo "This line is never output!" diff --git a/content/case.md b/content/content/case.md similarity index 98% rename from content/case.md rename to content/content/case.md index fc64a76..765fb0c 100644 --- a/content/case.md +++ b/content/content/case.md @@ -54,7 +54,7 @@ Another feature of case statements is that the possible values are narrowed, mea ``` nimrod let x = 2 -case (x and 3) + 7: +case (x and 0b11) + 7: of 7: echo "A" of 8: echo "B" of 9: echo "C" diff --git a/content/exceptions.md b/content/content/exceptions.md similarity index 100% rename from content/exceptions.md rename to content/content/exceptions.md diff --git a/content/content/footer.md b/content/content/footer.md new file mode 100644 index 0000000..0686e2a --- /dev/null +++ b/content/content/footer.md @@ -0,0 +1,2 @@ +
  • Contribute
  • Toggle dark mode
  • diff --git a/content/for_iterators.md b/content/content/for_iterators.md similarity index 100% rename from content/for_iterators.md rename to content/content/for_iterators.md diff --git a/content/getting_started.md b/content/content/getting_started.md similarity index 79% rename from content/getting_started.md rename to content/content/getting_started.md index 867064a..513f454 100644 --- a/content/getting_started.md +++ b/content/content/getting_started.md @@ -7,7 +7,7 @@ When installing Nim, you have two options: downloading a copy directly from git, ## Downloading a Nim Distribution To get started with Nim, head over to the [downloads page](http://nim-lang.org/download.html) and download the version you'd like. -The Windows distribution comes with the MinGW compiler, which is recommended, but if you'd like to use your own compiler, download the version without MinGW. +The Windows distribution comes with the MinGW compiler, which is recommended, but if you'd like to use your own compiler, download the version without MinGW. If you get an error like `Error: unhandled exception: The system cannot find the file specified.`, then make sure that the C compiler is on your path. On Mac and Linux, it is recommended to use either GCC or Clang. @@ -17,9 +17,9 @@ Once you have downloaded the appropriate distribution and extracted the files so To install Nim from git, ensure that you have gcc installed on Windows, Linux, and BSDs and clang on Mac. Afterwards, run the following series of commands to download and bootstrap Nim: ```console -$ git clone -b master git://github.com/Araq/Nimrod.git -$ cd Nimrod -$ git clone --depth 1 git://github.com/nimrod-code/csources +$ git clone -b master git://github.com/Araq/Nim.git +$ cd Nim +$ git clone --depth 1 git://github.com/nim-lang/csources $ cd csources $ sh build.sh # Replace with build.bat on windows $ cd .. diff --git a/content/hello_world.md b/content/content/hello_world.md similarity index 100% rename from content/hello_world.md rename to content/content/hello_world.md diff --git a/content/if_else_while.md b/content/content/if_else_while.md similarity index 97% rename from content/if_else_while.md rename to content/content/if_else_while.md index 026d43a..93b01c7 100644 --- a/content/if_else_while.md +++ b/content/content/if_else_while.md @@ -11,7 +11,7 @@ When inside a loop, `continue` can be used to skip the rest of the loop body and Along with [its other uses](/block/), the `block` statement can be used to create a label so that it's possible to break out of nested loops. ``` nim -import strutils, math +import strutils, random randomize() let answer = random(10) + 1 diff --git a/content/index.md b/content/content/index.md similarity index 100% rename from content/index.md rename to content/content/index.md diff --git a/content/oop.md b/content/content/oop.md similarity index 76% rename from content/oop.md rename to content/content/oop.md index 4befd90..9edbdd7 100644 --- a/content/oop.md +++ b/content/content/oop.md @@ -4,7 +4,7 @@ title: Object Oriented Programming # Object Oriented Programming -Object oriented programming is supported through inheritance and methods, which are virtual procedures. Methods work in the same was as [procs](/procs/), including UFCS, but the runtime type of the object that a method is called with is used to determine which version to call. +Object oriented programming is supported through inheritance and methods, which are virtual procedures. Methods work in the same way as [procs](/procs/), including UFCS, but the runtime type of the object that a method is called with is used to determine which version to call. Inheritance is created with the `of` keyword in the type declaration of an object. A method is overridden by creating a new method with parameter types of the subtype. @@ -38,3 +38,19 @@ woof meow 10 ``` + +## Testing subtypes + +It is also possible to check if an object is of a given subtype with the `of` keyword. For example, + +``` nimrod +echo(animals[0] of Dog) +echo(animals[0] of Cat) +echo(animals[0] of Animal) +``` +``` console +$ nim c -r of_op.nim +true +false +true +``` diff --git a/content/oop_macro.md b/content/content/oop_macro.md similarity index 54% rename from content/oop_macro.md rename to content/content/oop_macro.md index 3363943..0b13042 100644 --- a/content/oop_macro.md +++ b/content/content/oop_macro.md @@ -43,20 +43,16 @@ To get that nice notation, we can use a macro: ```nimrod import macros -macro class*(head: expr, body: stmt): stmt {.immediate.} = - # The macro is immediate so that it doesn't - # resolve identifiers passed to it +macro class*(head, body: untyped): untyped = + # The macro is immediate, since all its parameters are untyped. + # This means, it doesn't resolve identifiers passed to it. - var typeName, baseName: PNimrodNode + var typeName, baseName: NimNode - if head.kind == nnkIdent: - # `head` is expression `typeName` - # echo head.treeRepr - # -------------------- - # Ident !"Animal" - typeName = head + # flag if object should be exported + var exported: bool - elif head.kind == nnkInfix and $head[0] == "of": + if head.kind == nnkInfix and head[0].ident == !"of": # `head` is expression `typeName of baseClass` # echo head.treeRepr # -------------------- @@ -67,9 +63,57 @@ macro class*(head: expr, body: stmt): stmt {.immediate.} = typeName = head[1] baseName = head[2] + elif head.kind == nnkInfix and head[0].ident == !"*" and + head[2].kind == nnkPrefix and head[2][0].ident == !"of": + # `head` is expression `typeName* of baseClass` + # echo head.treeRepr + # -------------------- + # Infix + # Ident !"*" + # Ident !"Animal" + # Prefix + # Ident !"of" + # Ident !"RootObj" + typeName = head[1] + baseName = head[2][1] + exported = true + else: quit "Invalid node: " & head.lispRepr + # The following prints out the AST structure: + # + # import macros + # dumptree: + # type X = ref object of Y + # z: int + # -------------------- + # StmtList + # TypeSection + # TypeDef + # Ident !"X" + # Empty + # RefTy + # ObjectTy + # Empty + # OfInherit + # Ident !"Y" + # RecList + # IdentDefs + # Ident !"z" + # Ident !"int" + # Empty + + # create a type section in the result + result = + if exported: + # mark `typeName` with an asterisk + quote do: + type `typeName`* = ref object of `baseName` + else: + quote do: + type `typeName` = ref object of `baseName` + # echo treeRepr(body) # -------------------- # StmtList @@ -105,22 +149,26 @@ macro class*(head: expr, body: stmt): stmt {.immediate.} = # Ident !"this" # Ident !"age" - # create a new stmtList for the result - result = newStmtList() - # var declarations will be turned into object fields var recList = newNimNode(nnkRecList) + # expected name of constructor + let ctorName = newIdentNode("new" & $typeName) + # Iterate over the statements, adding `this: T` - # to the parameters of functions + # to the parameters of functions, unless the + # function is a constructor for node in body.children: case node.kind: of nnkMethodDef, nnkProcDef: - # inject `this: T` into the arguments - let p = copyNimTree(node.params) - p.insert(1, newIdentDefs(ident"this", typeName)) - node.params = p + # check if it is the ctor proc + if node.name.kind != nnkAccQuoted and node.name.basename == ctorName: + # specify the return type of the ctor proc + node.params[0] = typeName + else: + # inject `self: T` into the arguments + node.params.insert(1, newIdentDefs(ident("self"), typeName)) result.add(node) of nnkVarSection: @@ -131,56 +179,25 @@ macro class*(head: expr, body: stmt): stmt {.immediate.} = else: result.add(node) - # The following prints out the AST structure: - # - # import macros - # dumptree: - # type X = ref object of Y - # z: int - # -------------------- - # TypeSection - # TypeDef - # Ident !"X" - # Empty - # RefTy - # ObjectTy - # Empty - # OfInherit - # Ident !"Y" - # RecList - # IdentDefs - # Ident !"z" - # Ident !"int" - # Empty - - result.insert(0, - if baseName == nil: - quote do: - type `typeName` = ref object - else: - quote do: - type `typeName` = ref object of `baseName` - ) # Inspect the tree structure: # # echo result.treeRepr # -------------------- # StmtList - # StmtList - # TypeSection - # TypeDef - # Ident !"Animal" - # Empty - # RefTy - # ObjectTy - # Empty - # OfInherit - # Ident !"RootObj" - # Empty <= We want to replace this - # MethodDef - # ... + # TypeSection + # TypeDef + # Ident !"Animal" + # Empty + # RefTy + # ObjectTy + # Empty + # OfInherit + # Ident !"RootObj" + # Empty <= We want to replace this + # MethodDef + # ... - result[0][0][0][2][0][2] = recList + result[0][0][2][0][2] = recList # Lets inspect the human-readable version of the output # echo repr(result) @@ -190,26 +207,45 @@ macro class*(head: expr, body: stmt): stmt {.immediate.} = # name: string # age: int # - # method vocalize(this: Animal): string = + # method vocalize(this: Animal): string {.base.} = # "..." # - # method age_human_yrs(this: Animal): int = + # method age_human_yrs(this: Animal): int {.base.} = # this.age + # ... + # + # type + # Rabbit = ref object of Animal + # + # proc newRabbit(name: string; age: int): Rabbit = + # result = Rabbit(name: name, age: age) + # + # method vocalize(this: Rabbit): string = + # "meep" # --- class Animal of RootObj: var name: string var age: int - method vocalize: string = "..." - method age_human_yrs: int = this.age # `this` is injected + method vocalize: string {.base.} = "..." # use `base` pragma to annonate base methods + method age_human_yrs: int {.base.} = this.age # `this` is injected + proc `$`: string = "animal:" & this.name & ":" & $this.age class Dog of Animal: method vocalize: string = "woof" method age_human_yrs: int = this.age * 7 + proc `$`: string = "dog:" & this.name & ":" & $this.age class Cat of Animal: method vocalize: string = "meow" + proc `$`: string = "cat:" & this.name & ":" & $this.age + +class Rabbit of Animal: + proc newRabbit(name: string, age: int) = # the constructor doesn't need a return type + result = Rabbit(name: name, age: age) + method vocalize: string = "meep" + proc `$`: string = "rabbit:" & this.name & ":" & $this.age # --- @@ -220,6 +256,11 @@ animals.add(Cat(name: "Mitten", age: 10)) for a in animals: echo a.vocalize() echo a.age_human_yrs() + +let r = newRabbit("Fluffy", 3) +echo r.vocalize() +echo r.age_human_yrs() +echo r ``` ``` console $ nim c -r oopmacro.nim @@ -227,4 +268,7 @@ woof 70 meow 10 +meep +3 +rabbit:Fluffy:3 ``` diff --git a/content/primitives.md b/content/content/primitives.md similarity index 100% rename from content/primitives.md rename to content/content/primitives.md diff --git a/content/procs.md b/content/content/procs.md similarity index 95% rename from content/procs.md rename to content/content/procs.md index 9e3eb9f..39d0475 100644 --- a/content/procs.md +++ b/content/content/procs.md @@ -57,7 +57,7 @@ echo([[1, 2], [3, 4]]) # See varargs for # how echo works proc `^&*^@%`(a, b: string): string = - ## An confusingly named useless operator + ## A confusingly named useless operator result = a[0] & b[high(b)] assert("foo" ^&*^@% "bar" == "fr") @@ -78,7 +78,7 @@ proc `+`(a, b: string): string = proc `*`[T](a: T, b: int): T = result = zero for i in 0..b: - result = result + a + result = result + a # calls `+` from line 3 assert("a" * 10 == "aaaaaaaaaaa") ``` diff --git a/content/procvars.md b/content/content/procvars.md similarity index 82% rename from content/procvars.md rename to content/content/procvars.md index 53c6ad1..12a6921 100644 --- a/content/procvars.md +++ b/content/content/procvars.md @@ -20,10 +20,10 @@ $ nim c -r filterclosure.nim @[64, 128, 256] ``` -Existing procedures can also be passed as functions, but only if they are annotated with the `{.procvar.}` pragma. +Existing procedures can also be passed as functions, but only if they are annotated with the `{.procvar.}` pragma. This is because there may be default parameters, which must be specially handled by the compiler. ``` nimrod proc greaterThan32(x: int): bool {.procvar.} = x > 32 echo powersOfTwo.filter(greaterThan32) -``` \ No newline at end of file +``` diff --git a/content/seqs.md b/content/content/seqs.md similarity index 51% rename from content/seqs.md rename to content/content/seqs.md index e6b43ab..70bd106 100644 --- a/content/seqs.md +++ b/content/content/seqs.md @@ -19,14 +19,14 @@ for i, v in a: for i in 4..100: b.add(i * i) -b.delete(0) # takes «O(n)» time +b.delete(0) # takes O(n) time b = a[0] & b # Same as original b ``` ## Immutability -While sequences are dynamiclly allocated, they are still immutable. +Sequences are dynamiclly allocated (i.e. allocated on the heap, not the stack), but they are immutable unless marked as `var`. That means ``` nimrod let a = @[1, 2, 3] @@ -40,7 +40,16 @@ var b = @[1, 2, 3] b.add(4) ``` -will work without any problems. If wanted, a seq can be passed to a method with the `var` or `ref` annotation to make it modifiable, so +will work without any problems. Sequences passed as "argument by value" are not modifiable. For example, the following will fail to compile. + +``` nimrod +def do_something(mySeq: seq[int]) = + mySeq[0] = 2 # this is a compile-time error +var testSeq = [1, 2, 3] +do_something(testSeq) +``` + +`seq` arguments can be mutable if they are passed as "argument by reference", ie. the parameter is annotated with the `var` or `ref`: ``` nimrod proc foo(mySeq: var seq[int]) = @@ -51,3 +60,15 @@ foo(thisSeq) assert thisSeq[9] == 999 ``` + +You can copy a sequence passed as "argument by value" and modify the copy: + +``` nimrod +def do_something(mySeq: seq[int]) = + var varMySeq = mySeq # copy the seq + varMySeq[0] = 999 + assert varMySeq[0] == 999 +var testSeq = [1, 2, 3] +do_something(testSeq) +assert testSeq[0] == 1 +``` diff --git a/content/strings.md b/content/content/strings.md similarity index 56% rename from content/strings.md rename to content/content/strings.md index dfaf6c2..58b3eb1 100644 --- a/content/strings.md +++ b/content/content/strings.md @@ -16,7 +16,7 @@ echo """ proc re(s: string): string = s -echo r" "" " +echo r".""." echo re"\b[a-z]++\b" ``` ``` console @@ -29,17 +29,23 @@ words words words ⚑ - " +.". \b[a-z]++\b ``` -There are several types of strings literals: +There are several types of string literals: - Quoted Strings: Created by wrapping the body in triple quotes, they never interpret escape codes - - Raw Strings: created by prefixing the string with an `r`. There are no escape sequences don't work, except for `"`, which can be escaped as `""` - - Proc Strings: raw strings, but the method name that prefixes the string is called + - Raw Strings: created by prefixing the string with an `r`. They do not interpret escape sequences, except for `""`, which is interpreted as `"`. This means that `r"\b[a-z]\b"` is interpreted as `\b[a-z]\b` instead of failing to compile with a syntax error. + - Proc Strings: raw strings, but the method name that prefixes the string is called, so that `foo"12\"` -> `foo(r"12\")`. + +Strings are null-terminated, so that `cstring("foo")` requires zero copying. However, you should be careful that the lifetime of the cstring does not exceed the lifetime of the string it is based upon. + +Strings can also almost be thought of as `seq[char]` with respect to assignment semantics. See [seqs][] + +[seqs]: /seqs/#immutability ## A note about unicode Unicode symbols are allowed in strings, but are not treated in any special way, so if you want count glyphs or uppercase unicode symbols, you must use the `unicode` module. -Strings are generally considered to be encoded as UTF-8, so because of unicode's backwards compatibility, can be treated exactly as ASCII, with all values above 127 ignored. \ No newline at end of file +Strings are generally considered to be encoded as UTF-8, so because of unicode's backwards compatibility, can be treated exactly as ASCII, with all values above 127 ignored. diff --git a/content/toc.md b/content/content/toc.md similarity index 92% rename from content/toc.md rename to content/content/toc.md index 57c6767..b8318f9 100644 --- a/content/toc.md +++ b/content/content/toc.md @@ -1,5 +1,3 @@ -## Pages - * [Getting Started](/getting_started/) * [Hello World](/hello_world/) * [Variables](/variables/) @@ -24,5 +22,4 @@ * [Object Oriented Programming](/oop/) * [OOP Macro](/oop_macro/) - {: #toc-list} diff --git a/content/types.md b/content/content/types.md similarity index 100% rename from content/types.md rename to content/content/types.md diff --git a/content/types/distinct.md b/content/content/types/distinct.md similarity index 100% rename from content/types/distinct.md rename to content/content/types/distinct.md diff --git a/content/types/enums.md b/content/content/types/enums.md similarity index 100% rename from content/types/enums.md rename to content/content/types/enums.md diff --git a/content/types/objects.md b/content/content/types/objects.md similarity index 96% rename from content/types/objects.md rename to content/content/types/objects.md index 7f61c1a..1c457c5 100644 --- a/content/types/objects.md +++ b/content/content/types/objects.md @@ -26,7 +26,7 @@ let joe = Animal(name : "Joe", species : "H. sapiens", age : 23) -assert not carl.dead +assert(not carl.dead) for i in 0..10: carl.sleep() assert carl.dead @@ -54,9 +54,9 @@ You might ask whether there is a more concise way of initializing reference typ ``` nimrod type - PAnimal* = ref Animal + AnimalRef* = ref Animal -let spot = PAnimal(name: "Spot", +let spot = AnimalRef(name: "Spot", species: "C. lupus", age: 1) ``` @@ -67,4 +67,4 @@ In many cases it is only wanted to have the object be a reference type, which is type Thing* = ref object positionX*, positionY*: int -``` \ No newline at end of file +``` diff --git a/content/types/range.md b/content/content/types/range.md similarity index 100% rename from content/types/range.md rename to content/content/types/range.md diff --git a/content/varargs.md b/content/content/varargs.md similarity index 100% rename from content/varargs.md rename to content/content/varargs.md diff --git a/content/variables.md b/content/content/variables.md similarity index 100% rename from content/variables.md rename to content/content/variables.md diff --git a/content/variables/result.md b/content/content/variables/result.md similarity index 100% rename from content/variables/result.md rename to content/content/variables/result.md diff --git a/content/variables/type_casting_inference.md b/content/content/variables/type_casting_inference.md similarity index 100% rename from content/variables/type_casting_inference.md rename to content/content/variables/type_casting_inference.md diff --git a/content/fonts/fontelloe.eot b/content/fonts/fontelloe.eot deleted file mode 100644 index cffe901..0000000 Binary files a/content/fonts/fontelloe.eot and /dev/null differ diff --git a/content/fonts/fontellos.svg b/content/fonts/fontellos.svg deleted file mode 100644 index 5a187a3..0000000 --- a/content/fonts/fontellos.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - -Copyright (C) 2014 by original authors @ fontello.com - - - - - - - - - - \ No newline at end of file diff --git a/content/fonts/fontellot.ttf b/content/fonts/fontellot.ttf deleted file mode 100644 index 6f31fe8..0000000 Binary files a/content/fonts/fontellot.ttf and /dev/null differ diff --git a/content/fonts/fontellow.woff b/content/fonts/fontellow.woff deleted file mode 100644 index 5be5972..0000000 Binary files a/content/fonts/fontellow.woff and /dev/null differ diff --git a/content/images/triangle.png b/content/images/triangle.png deleted file mode 100644 index 985a136..0000000 Binary files a/content/images/triangle.png and /dev/null differ diff --git a/content/opengl/triangle.md b/content/opengl/triangle.md deleted file mode 100644 index 5da0d17..0000000 --- a/content/opengl/triangle.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: OpenGL - Triangle ---- -# OpenGL: Triangle - -The following code depends on the ``opengl`` and ``nim-glfw`` packages which -can be installed via babel by executing ``babel install opengl@#head nim-glfw@#head``. -You will need the GLFW DLL in order to run this on Windows. - -![Triangle Windows](https://nim-by-example.github.io/images/triangle.png) - -One thing to keep in mind when writing OpenGL code in Nim is that ``float`` -is actually ``float64``. But vertices must be ``float32`` so you must explicitly -specify that by casting or using ``'f32`` as is done in the example. - -```nimrod -import os, glfw/glfw, opengl, times, math - -proc assertShader(shader: GLuint) = - var status: GLint - glGetShaderiv(shader, GL_COMPILE_STATUS, addr status) - if status != GL_TRUE: - var buff: array[512, char] - glGetShaderInfoLog(shader, 512, nil, buff) - echo(buff) - assert false - -const - vertexSource = """ -#version 150 - -in vec2 position; -in vec3 color; - -out vec3 Color; - -void main() -{ - Color = color; - gl_Position = vec4(position, 0.0, 1.0); -} -""" - fragmentSource = """ -#version 150 - -in vec3 Color; - -out vec4 outColor; - -void main() -{ - outColor = vec4(Color, 1.0); -} -""" - - -proc setup(shaderProgram: var TGLUint) = - var vertices = [ - 0.0'f32, 0.5, 1, 0, 0, - 0.5, -0.5, 0, 1, 0, - -0.5, -0.5, 0, 0, 1 - ] - echo(vertices.repr) - var vertexBuffer: GLuint - glGenBuffers(1, addr vertexBuffer) - echo("Verter Buff: ", vertexBuffer) - - var vertexArray: GLuint - glGenVertexArrays(1, addr vertexArray) - glBindVertexArray(vertexArray) - - - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer) - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices).int32, addr vertices, - GL_STATIC_DRAW) - - var vertexShader = glCreateShader(GL_VERTEX_SHADER) - var vertexSrcArray = [vertexSource.cstring] - glShaderSource(vertexShader, 1, cast[cstringArray](addr vertexSrcArray), nil) - glCompileShader(vertexShader) - assertShader(vertexShader) - - var fragmentShader = glCreateShader(GL_FRAGMENT_SHADER) - var fragmentSrcArray = [fragmentSource.cstring] - glShaderSource(fragmentShader, 1, cast[cstringArray](addr fragmentSrcArray), - nil) - glCompileShader(fragmentShader) - assertShader(fragmentShader) - - shaderProgram = glCreateProgram() - glAttachShader(shaderProgram, vertexShader) - glAttachShader(shaderProgram, fragmentShader) - - # Apparently this is not necessary according to http://open.gl - glBindFragDataLocation(shaderProgram, 0, "outColor") - - glLinkProgram(shaderProgram) - glUseProgram(shaderProgram) - - # Vertex data <-> attributes - var posAttrib = glGetAttribLocation(shaderProgram, "position").gluint - glEnableVertexAttribArray(posAttrib) - glVertexAttribPointer(posAttrib, 2, cGL_FLOAT, false, - 5*sizeof(GLFloat).int32, nil) - - var colAttrib = glGetAttribLocation(shaderProgram, "color").gluint - glEnableVertexAttribArray(colAttrib) - glVertexAttribPointer(colAttrib, 3, cGL_FLOAT, false, - 5*sizeof(GLFloat).int32, - cast[pointer](2*sizeof(GLFloat))) - -when isMainModule: - glfw.init() - var win = newWin() - win.makeContextCurrent() - - loadExtensions() - - var shaderProgram: TGLuint - setup(shaderProgram) - - while not win.shouldClose: - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT) - - glDrawArrays(GL_TRIANGLES, 0, 3) - win.swapBufs() - - pollEvents() - - win.destroy() - glfw.terminate() -``` diff --git a/content/stylesheets/colorful.css b/content/stylesheets/colorful.css deleted file mode 100644 index f74addf..0000000 --- a/content/stylesheets/colorful.css +++ /dev/null @@ -1,72 +0,0 @@ -/* pygments-css colorful */ -code[class^='language-'] .hll:not([id^='MathJax']) { background-color: #ffffcc } -code[class^='language-'] .c:not([id^='MathJax']) { color: #808080 } /* Comment */ -code[class^='language-'] .err:not([id^='MathJax']) { color: #F00000; background-color: #F0A0A0 } /* Error */ -code[class^='language-'] .k:not([id^='MathJax']) { color: #008000; font-weight: bold } /* Keyword */ -code[class^='language-'] .o:not([id^='MathJax']) { color: #303030 } /* Operator */ -code[class^='language-'] .cm:not([id^='MathJax']) { color: #808080 } /* Comment.Multiline */ -code[class^='language-'] .cp:not([id^='MathJax']) { color: #507090 } /* Comment.Preproc */ -code[class^='language-'] .c1:not([id^='MathJax']) { color: #808080 } /* Comment.Single */ -code[class^='language-'] .cs:not([id^='MathJax']) { color: #cc0000; font-weight: bold } /* Comment.Special */ -code[class^='language-'] .gd:not([id^='MathJax']) { color: #A00000 } /* Generic.Deleted */ -code[class^='language-'] .ge:not([id^='MathJax']) { font-style: italic } /* Generic.Emph */ -code[class^='language-'] .gr:not([id^='MathJax']) { color: #FF0000 } /* Generic.Error */ -code[class^='language-'] .gh:not([id^='MathJax']) { color: #000080; font-weight: bold } /* Generic.Heading */ -code[class^='language-'] .gi:not([id^='MathJax']) { color: #00A000 } /* Generic.Inserted */ -code[class^='language-'] .go:not([id^='MathJax']) { color: #808080 } /* Generic.Output */ -code[class^='language-'] .gp:not([id^='MathJax']) { - color: #c65d09; - font-weight: bold; - /* NOTE: Hacks to allow copy-paste */ - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} /* Generic.Prompt */ -code[class^='language-'] .gs:not([id^='MathJax']) { font-weight: bold } /* Generic.Strong */ -code[class^='language-'] .gu:not([id^='MathJax']) { color: #800080; font-weight: bold } /* Generic.Subheading */ -code[class^='language-'] .gt:not([id^='MathJax']) { color: #0040D0 } /* Generic.Traceback */ -code[class^='language-'] .kc:not([id^='MathJax']) { color: #008000; font-weight: bold } /* Keyword.Constant */ -code[class^='language-'] .kd:not([id^='MathJax']) { color: #008000; font-weight: bold } /* Keyword.Declaration */ -code[class^='language-'] .kn:not([id^='MathJax']) { color: #008000; font-weight: bold } /* Keyword.Namespace */ -code[class^='language-'] .kp:not([id^='MathJax']) { color: #003080; font-weight: bold } /* Keyword.Pseudo */ -code[class^='language-'] .kr:not([id^='MathJax']) { color: #008000; font-weight: bold } /* Keyword.Reserved */ -code[class^='language-'] .kt:not([id^='MathJax']) { color: #303090; font-weight: bold } /* Keyword.Type */ -code[class^='language-'] .m:not([id^='MathJax']) { color: #6000E0; font-weight: bold } /* Literal.Number */ -code[class^='language-'] .s:not([id^='MathJax']) { background-color: #fff0f0 } /* Literal.String */ -code[class^='language-'] .na:not([id^='MathJax']) { color: #0000C0 } /* Name.Attribute */ -code[class^='language-'] .nb:not([id^='MathJax']) { color: #007020 } /* Name.Builtin */ -code[class^='language-'] .nc:not([id^='MathJax']) { color: #B00060; font-weight: bold } /* Name.Class */ -code[class^='language-'] .no:not([id^='MathJax']) { color: #003060; font-weight: bold } /* Name.Constant */ -code[class^='language-'] .nd:not([id^='MathJax']) { color: #505050; font-weight: bold } /* Name.Decorator */ -code[class^='language-'] .ni:not([id^='MathJax']) { color: #800000; font-weight: bold } /* Name.Entity */ -code[class^='language-'] .ne:not([id^='MathJax']) { color: #F00000; font-weight: bold } /* Name.Exception */ -code[class^='language-'] .nf:not([id^='MathJax']) { color: #0060B0; font-weight: bold } /* Name.Function */ -code[class^='language-'] .nl:not([id^='MathJax']) { color: #907000; font-weight: bold } /* Name.Label */ -code[class^='language-'] .nn:not([id^='MathJax']) { color: #0e84b5; font-weight: bold } /* Name.Namespace */ -code[class^='language-'] .nt:not([id^='MathJax']) { color: #007000 } /* Name.Tag */ -code[class^='language-'] .nv:not([id^='MathJax']) { color: #906030 } /* Name.Variable */ -code[class^='language-'] .ow:not([id^='MathJax']) { color: #000000; font-weight: bold } /* Operator.Word */ -code[class^='language-'] .w:not([id^='MathJax']) { color: #bbbbbb } /* Text.Whitespace */ -code[class^='language-'] .mf:not([id^='MathJax']) { color: #6000E0; font-weight: bold } /* Literal.Number.Float */ -code[class^='language-'] .mh:not([id^='MathJax']) { color: #005080; font-weight: bold } /* Literal.Number.Hex */ -code[class^='language-'] .mi:not([id^='MathJax']) { color: #0000D0; font-weight: bold } /* Literal.Number.Integer */ -code[class^='language-'] .mo:not([id^='MathJax']) { color: #4000E0; font-weight: bold } /* Literal.Number.Oct */ -code[class^='language-'] .sb:not([id^='MathJax']) { background-color: #fff0f0 } /* Literal.String.Backtick */ -code[class^='language-'] .sc:not([id^='MathJax']) { color: #0040D0 } /* Literal.String.Char */ -code[class^='language-'] .sd:not([id^='MathJax']) { color: #D04020 } /* Literal.String.Doc */ -code[class^='language-'] .s2:not([id^='MathJax']) { background-color: #fff0f0 } /* Literal.String.Double */ -code[class^='language-'] .se:not([id^='MathJax']) { color: #606060; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */ -code[class^='language-'] .sh:not([id^='MathJax']) { background-color: #fff0f0 } /* Literal.String.Heredoc */ -code[class^='language-'] .si:not([id^='MathJax']) { background-color: #e0e0e0 } /* Literal.String.Interpol */ -code[class^='language-'] .sx:not([id^='MathJax']) { color: #D02000; background-color: #fff0f0 } /* Literal.String.Other */ -code[class^='language-'] .sr:not([id^='MathJax']) { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */ -code[class^='language-'] .s1:not([id^='MathJax']) { background-color: #fff0f0 } /* Literal.String.Single */ -code[class^='language-'] .ss:not([id^='MathJax']) { color: #A06000 } /* Literal.String.Symbol */ -code[class^='language-'] .bp:not([id^='MathJax']) { color: #007020 } /* Name.Builtin.Pseudo */ -code[class^='language-'] .vc:not([id^='MathJax']) { color: #306090 } /* Name.Variable.Class */ -code[class^='language-'] .vg:not([id^='MathJax']) { color: #d07000; font-weight: bold } /* Name.Variable.Global */ -code[class^='language-'] .vi:not([id^='MathJax']) { color: #3030B0 } /* Name.Variable.Instance */ -code[class^='language-'] .il:not([id^='MathJax']) { color: #0000D0; font-weight: bold } /* Literal.Number.Integer.Long */ diff --git a/content/stylesheets/cotton_candy.css b/content/stylesheets/cotton_candy.css deleted file mode 100644 index f64558f..0000000 --- a/content/stylesheets/cotton_candy.css +++ /dev/null @@ -1,8 +0,0 @@ -#main code, code * { color: #675D69; } -code[class^='language-'] .k:not([id^='MathJax']) { color: #143A77; } -code[class^='language-'] .kp:not([id^='MathJax']) { color: #8C5DC7; } -code[class^='language-'] .kd:not([id^='MathJax']) { color: #8C5DC7; } -code[class^='language-'] .mi:not([id^='MathJax']) { color: #8C5DC7; } -code[class^='language-'] .s:not([id^='MathJax']) { color: #0060B0; } -code[class^='language-'] .c:not([id^='MathJax']) { color: #91B9A3; } -code[class^='language-'] .o:not([id^='MathJax']) { color: #009DE7; } \ No newline at end of file diff --git a/content/stylesheets/fontello.css b/content/stylesheets/fontello.css deleted file mode 100644 index 082daba..0000000 --- a/content/stylesheets/fontello.css +++ /dev/null @@ -1,30 +0,0 @@ -@font-face { - font-family: 'fontello'; - src: url('/fonts/fontelloe.eot?23005170'); - src: url('/fonts/fontelloe.eot?23005170#iefix') format('embedded-opentype'), - url('/fonts/fontellow.woff?23005170') format('woff'), - url('/fonts/fontellot.ttf?23005170') format('truetype'), - url('/fonts/fontellos.svg?23005170#fontello') format('svg'); - font-weight: normal; - font-style: normal; -} - -[class^="icon-"]:before, [class*=" icon-"]:before { - font-family: "fontello"; - font-style: normal; - font-weight: normal; - speak: none; - - display: inline-block; - text-decoration: inherit; - width: 1em; - margin-right: .2em; - text-align: center; - - font-variant: normal; - text-transform: none; -} - -.icon-check:before { content: '\e800'; } /* '' */ -.icon-star:before { content: '\e801'; } /* '' */ -.icon-fork:before { content: '\e802'; } /* '' */ \ No newline at end of file diff --git a/content/stylesheets/main.css b/content/stylesheets/main.css deleted file mode 100644 index 3994929..0000000 --- a/content/stylesheets/main.css +++ /dev/null @@ -1,192 +0,0 @@ -* { - margin: 0; - padding: 0; - - font-family: Palatino, serif; - box-sizing: border-box; -} - -body { - background: #F5F7F6; - color: black; - line-height: 20px; - text-rendering: optimizelegibility; -} - -a { - text-decoration: none; -} - -a:link, a:visited{ - color: #B45D47; -} - -a:hover { - color: #FE3B3B; -} - -#main { - position: absolute; - - left: 255px; - - max-width: 600px; - - margin-bottom: 50px; -} - -#main #gh-buttons { - float: right; - margin-bottom: 22px; -} - -#main #starcount { - line-height: 20px; - font-size: 15px; - text-align: center; - color: #000; - - position: absolute; - display: block; - float: right; - right: 5px; - width: 3em; - background: #FFF; - border: 1px solid #CCC; - border-radius: 3px; - - height: 20px; -} - -#main hr { - background: #CCC; - border: none; - margin: 1em; - margin-bottom: 1.3em; - height: 1px; -} - -#main h1 { - font-size: 40px; - font-weight: normal; - - line-height: 40px; - - letter-spacing: -1px; - margin-bottom: 0.75em; -} - -#main h2 { - margin-top: 1em; -} - -#main p { - margin: 20px 0px; - margin-right: 1em; - line-height: 20px; -} - -#main ul, #main ol { - margin: 20px; -} - -#main ul li { - list-style-type: square; -} - -#main table, th, td { - border-collapse: collapse; - border: 1px solid #CCC; - background-color: #FFF; - padding: 3px; -} - -#main table { - box-shadow: 1px 3px 12px #BBB; - margin: 20px 10px 20px 0px; -} - -#main code, code * { - font-family: Monaco, Menlo, Consolas, "Courier New", monospace; -} - -#main code { - background: #FFFFFF; - padding: 0px 3px; -} - -#main pre code { /* Block Code */ - display: block; - word-wrap: break-word; - overflow: auto; - - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ - - border-radius: 3px; - background:#FFF; - box-shadow: 1px 3px 12px #BBB; - padding: 10px 15px; - margin: 5px 10px 10px 5px; -} - -#main span.line-numbers { - display: none; -} - -#sidebar { - float: left; - margin-top: 20px; - margin-left: 20px; - width: 211px; - - padding: 20px; - padding-left: 30px; - - border-right: 1px solid #ccc; - - font-size: 90%; - line-height: 20px; - box-sizing: border-box; -} - -#sidebar h2 { - text-transform: uppercase; - font-size: 16px; - color: #470000; - letter-spacing: 1px; - line-height: 20px; -} - -#sidebar ul { - position: relative; - left: 20px; - list-style: decimal-leading-zero; - list-style-position: outside; -} - -#sidebar ul li ul { - width: 100px -} - -#sidebar #toc-list { - left: 20px; -} - -#sidebar a.visited:before { /* selected with JS */ - content: ""; - font-family: "fontello"; - position: absolute; - left: -43px; - color: #EEE; - text-shadow: -1px 0 #2B2B2B, 0 1px #2B2B2B, 1px 0 #2B2B2B, 0 -1px #2B2B2B -} - -/* Chrome */ -@media screen and (-webkit-min-device-pixel-ratio:0) { - #sidebar ul { text-indent: -5px; } - #sidebar #toc-list { left: 25px; } -} diff --git a/layouts/default.html b/layouts/default.html index 1a2f879..030c2b6 100644 --- a/layouts/default.html +++ b/layouts/default.html @@ -1,71 +1,55 @@ - - + + - Nim by Example - <%= @item[:title] %> - - - - - - - + <% if @config[:debug] %> + <% for file in @config[:stylesheets] %> + .css"> + <% end %> + <% for file in @config[:scripts] %> + + <% end %> + <% else %> + + + <% end %> + Nim by Example - <%= @item[:title] %> + + + -
    -

    - + +
    <%= yield %> +
    + +
    + ↽ + ⇁
    + + diff --git a/lib/helpers.rb b/lib/helpers.rb new file mode 100644 index 0000000..28bda4a --- /dev/null +++ b/lib/helpers.rb @@ -0,0 +1,19 @@ +def all_js(files) + js_arr = [] + for file in files + item = @items.find{|i| i.identifier == "/assets/js/#{file}/"} + puts "File #{file} doesn't exist!" unless item + js_arr << item.compiled_content + end + js_arr.join("\n") +end + +def all_css(files) + css_arr = [] + for file in files + item = @items.find{|i| i.identifier == "/assets/css/#{file}/"} + puts "File #{file} doesn't exist!" unless item + css_arr << item.compiled_content + end + css_arr.join("\n") +end diff --git a/nanoc.yaml b/nanoc.yaml index bf8c595..d614d61 100644 --- a/nanoc.yaml +++ b/nanoc.yaml @@ -29,6 +29,8 @@ prune: # .git, .svn etc. exclude: [ '.git', '.hg', '.svn', 'CVS' ] +string_pattern_type: legacy + # The data sources where nanoc loads its data from. This is an array of # hashes; each array element represents a single data source. By default, # there is only a single data source that reads data from the “content/” and @@ -38,6 +40,8 @@ data_sources: # The type is the identifier of the data source. By default, this will be # `filesystem_unified`. type: filesystem_unified + identifier_type: legacy + encoding: utf-c8 # The path where items should be mounted (comparable to mount points in # Unix-like systems). This is “/” by default, meaning that items will have @@ -60,3 +64,15 @@ data_sources: # The default encoding for all files in `content/` and `layouts/`. encoding: utf-8 + + +debug: false + +scripts: + - main + +stylesheets: + - normalize + - colorful + - main + - monokai diff --git a/nimrod-by-example.sublime-project b/nimrod-by-example.sublime-project deleted file mode 100644 index 2e57953..0000000 --- a/nimrod-by-example.sublime-project +++ /dev/null @@ -1,29 +0,0 @@ -{ - "folders": - [ - { "path": "content" }, - { "path": "layouts" }, - { "path": "lib" }, - { - "path": "./", - "folder_exclude_patterns": ["output", - "tmp", - "content", - "layouts", - "lib"] - } - ], - "build_systems": - [ - { - "name": "View", - "cmd": ["./view"], - "working_dir": "$project_path/" - }, - { - "name": "Compile", - "cmd": ["nanoc"], - "working_dir": "$project_path/" - } - ] -} \ No newline at end of file diff --git a/testexamples.nim b/testexamples.nim index 9f205ec..e5ff993 100644 --- a/testexamples.nim +++ b/testexamples.nim @@ -1,10 +1,13 @@ import md5, re, os, strutils, osproc let - markdownFilesGlob = getCurrentDir() / "content" / "*.md" + markdownFilesGlob = getCurrentDir() / "content" / "content" configFilePath = getCurrentDir() / "validcodehashes.txt" -for filePath in walkFiles(markdownFilesGlob): +for filePath in walkDirRec(markdownFilesGlob): + if filePath.splitFile.ext != ".md": + continue + let file = open(filePath, fmRead) let fileContents = file.readAll() file.close() diff --git a/validcodehashes.txt b/validcodehashes.txt index 84aae9a..f35d556 100644 --- a/validcodehashes.txt +++ b/validcodehashes.txt @@ -1,18 +1,23 @@ 489fd1e2356eb85f81bac48e45b186a7 +260d9667bbbc34ce79da5d60efecef02 ade4a4b3b6973bbb44f2e74aee1954f7 ef380e36bcc0ebf11902cefaa10ec31b +a043c1e16c84d2f1be0a9a6193d30ac0 26ded9e69879069fb8970403e87a24c9 b243592b06e93bb3cf1f7d62a25abaa3 3f3dfdee017d0c329d594e9fe038ed9f -cf09b588bb8b3c6979d24dcaff932c68 +4d390aa1b44e1bb953e12e210985c85a 4bb57235ab6f4f0dd1eea58a769570c5 394ca46d1bf22dedef7e6e753bd033c8 8afe80a509d316a3feb3caa1c985760a 0bdba4c56b6172c86726f424b4186baf 9551565b83418876b5211869acbcf7cc -ac4fe7f722b390100501e638ce8a9750 -f770b25468d042a02822e90df0848f35 +24614b0b8792a9afc184e4d63e345981 +d20fe9a9133bee2ef13c3b19ef540958 +217de4ce8743609c7592a3d75264b17d +36c0a24d4e54348f950ff421a33dcd38 +08b581ad308e3614335426ad8188b1ef 10ae94a28a0d8f23aff5afaa0367cf27 1865b827bef365e6422beb6bc076a25d 398863bccd3691b42500dfa143a3230b @@ -21,18 +26,31 @@ b8875a112bc13ea83556bcf385c1160b bee0509ab4bcf36510a85081d563057b 30111c31170d8cd9979ae7d88fa276e7 0e641a70cbd7b3e955bb29bde934f36e -ad9e1e896361b0313c3ba66f793f4e6b +9c6750cad12656f497e5e6eb6896f5a1 d599ef057eaaac83139eb8f949cef356 e0e0e0b5724e296371d1704996096343 2d60def87d4fa95e26b9f8eade4b0baa -180c2775b35bd48de55453713ccb5828 +d10f498d7a0d1e8693f7e1612822405f d01dfb20f1d8c1741eef320e82bfcdc2 4f19f7a7103d8aec86dd2ab995e5a0a8 fbb7977d27de5251fa736a627aaa8311 847d1c4525d9056206a1e4f4855a9e10 e4b29a303e0a22cab1f2bfb769ce66c5 -260d9667bbbc34ce79da5d60efecef02 -24614b0b8792a9afc184e4d63e345981 -217de4ce8743609c7592a3d75264b17d -36c0a24d4e54348f950ff421a33dcd38 -0b0bdbed7863d3ec82d2d8cb628562ed \ No newline at end of file +9eec8a1ad6f93080de5bcff05d8c5949 +d62e74f9c0aa9077ec40ea4d038927d0 +bf5bdad17535aa70efc569742eb1101f +c3da4dbe65a64c00ebc210a71e821ed9 +02b30eadfb0591b8f723dd9277def002 +d2657654df16c22a97903846ae9b3eec +84daadf080ac9b00870727cbb04f4758 +deea30998a85ce603a7a38bb017de77b +a79167cf1a4c8d0347a55cb2676ffae3 +9c16fb893a312d6bd6b260625a4b9b0c +b98257acda2d22827ed107f58c8a5ed8 +f770b25468d042a02822e90df0848f35 +397f231567a0f2ccd17a1a2b460d1c89 +1cf49f03f1017f8babc9c517829266ae +4749fe1ac61b589a786fee5466bb4a52 +abbe9a423e8c585e66f98deb6f7c303b +0e4bc99af4cd0c36e5af48ab2f5a5aa3 +3dec7aae6d5b68e432c47200850be8fc \ No newline at end of file diff --git a/wercker.yml b/wercker.yml index f780e54..0eb1e2d 100644 --- a/wercker.yml +++ b/wercker.yml @@ -1,13 +1,14 @@ -box: flaviut/nim-by-example-build-vm@0.0.6 +box: flaviut/nim-by-example-build-vm:0.1.2 build: steps: - script: name: build code: | - source /home/ubuntu/.rvm/scripts/rvm - git remote add publish $GIT_CREDENTIALS - git config --global user.email "you@example.com" - git config --global user.name "Your Name" + source /usr/local/rvm/scripts/rvm + git remote add publish 'git@github.com:nim-by-example/nim-by-example.github.io.git' + git config --global user.email 'nim-by-example.github.io' + git config --global user.name 'Builder' + git config --global push.default simple git checkout master nanoc cp -r ./output/. ./ @@ -16,7 +17,15 @@ build: git commit -am'Build Site' deploy: steps: + - script: + name: ssh-keys + code: | + mkdir -p ~/.ssh/ + echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' > ~/.ssh/known_hosts + echo -e "$GIT_CREDENTIALS" > ~/.ssh/id_rsa + chmod 0600 ~/.ssh/id_rsa + chmod 0644 ~/.ssh/known_hosts - script: name: deploy code: | - git push --force publish > /dev/null 2>&1 + git push --force publish