From b585d7ee7724970904ba0bd77d84c2337159b4b3 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Thu, 27 Feb 2020 13:50:46 -0500 Subject: [PATCH] Convert stylesheet to SCSS and preprocess with SASS. This CSS preprocessing tool seems pretty helpful for reducing repetition in stylesheets. While it does not make much difference now I hope to make more use of its features in the future. --- .gitignore | 1 + Rules | 11 +++ content/style.css | 167 ------------------------------------- content/style.scss | 148 ++++++++++++++++++++++++++++++++ lib/css-clean-selectors.rb | 53 ++++++++++++ lib/css-source.rb | 44 ++++++++++ 6 files changed, 257 insertions(+), 167 deletions(-) delete mode 100644 content/style.css create mode 100644 content/style.scss create mode 100644 lib/css-clean-selectors.rb create mode 100644 lib/css-source.rb diff --git a/.gitignore b/.gitignore index b186842..0810595 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.sass-cache /crash.log /output /tmp diff --git a/Rules b/Rules index a7dffee..d9130f0 100644 --- a/Rules +++ b/Rules @@ -92,6 +92,17 @@ compile '/license/cc*.xhtml' do write to_xhtml end +compile '/**/*.scss' do + filter :sass, syntax: :scss + filter :css_source, uribase: \ + "https://git.draconx.ca/gitweb/homepage.git/blob/" + + @item[:gitrev] + ":" + filter :css_clean_selectors, \ + preserve_comments: true, \ + preserve_hacks: true + write @item.identifier.without_ext + '.css' +end + passthrough '/**/*' layout '/**/*.xsl', :xsl layout '/**/*', :erb diff --git a/content/style.css b/content/style.css deleted file mode 100644 index 1028de0..0000000 --- a/content/style.css +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Nick's web site: default stylesheet - * - * Copyright © 2018 Nick Bowler - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -body { - font-family: sans-serif; - margin: 1em; -} - -h1 { - font-size: 2em; - max-width: 30em; /* 60rem */ -} - -h2 { - font-size: 1.5em; - max-width: 40em; /* 60rem */ -} - -a:link { - color: mediumblue; -} - -a:active { - color: red; -} - -a:visited { - color: purple; -} - -p, body>div { - text-align: justify; - padding: 0; - margin: 1em 0; - max-width: 50em; -} - -ul, ol, dl { - max-width: 50em; - padding: 0; - margin: 0; -} - -dt, dd, li { - text-align: justify; - padding: 0; -} -li { margin: 0 0 0 2em; } -dd { margin: 0 0 0 1em; } - -ul.ordered>li { - list-style: none; -} - -ul.ordered>li>span:first-child, ul.ordered>li>*:first-child>span:first-child { - display: inline-block; - text-align: right; - - margin-left: -1.8em; - min-width: 1.8em; -} - -hr { - clear: both; - text-align: left; - margin: 0.5em 0; - max-width: 50em; - border: 0; - border-top: 1px solid lightgray; -} - -small.permalink { - font-size: small; - color: slategray; -} -.permalink a:link, .permalink a:visited { - color: slategray; -} - -@media not screen { - small.permalink { - visibility: hidden; - } -} - -#footer { - max-width: 44em; - margin: 0; - padding: 0 3em; - text-align: center; -} - -#footer>p { - display: inline-block; - color: slategray; - font-size: 0.8em; - max-width: 100%; - margin: 0.2em 0; -} - -kbd { - font-family: monospace; - font-size: small; -} - -kbd::before { - content: "% "; -} - -#breadcrumbs, #sitetitle { text-align: left; } -#breadcrumbs>*, #sitetitle>* { font-size: 0.8em; } - -#sitetitle>* { - float: right; - display: inline-block; -} - -#breadcrumbs>strong { - vertical-align: top; - margin: 0; - padding: 0; -} - -#breadcrumbs>ul { - list-style-type: none; - vertical-align: top; - display: inline; - margin: 0; - padding: 0; -} - -#breadcrumbs>ul>li { - display: inline; - padding: 0; - margin: 0; -} - -#breadcrumbs>ul>li::before { content: "/ " } -#breadcrumbs>ul>li:first-child::before { content: none; } - -@media (max-width: 512px) { - body { margin: 0.6em; } - ul ul { margin-left: -1.2em; } - dd { margin: 0; } -} - -@media (max-width: 28em) { li, dd, dt, p { text-align: left; } } -@media (max-width: 35em) { - #sitetitle>* { float: none; } - #footer { padding: 0 1em; } -} diff --git a/content/style.scss b/content/style.scss new file mode 100644 index 0000000..79d4ffb --- /dev/null +++ b/content/style.scss @@ -0,0 +1,148 @@ +/* + * Nick's web site: default stylesheet + * + * Copyright © 2018-2020 Nick Bowler + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// colour definitions +$backgroundcolour: #ffffff; +$foregroundcolour: #000000; + +$linkdefaultcolour: #0000cd; +$linkactivecolour: #ff0000; +$linkvisitedcolour: #800080; + +$ruledefaultcolour: #d3d3d3; + +$annotationcolour: #708090; + +@mixin header_size($maxwidth, $fontsize) { + font-size: $fontsize; + max-width: 1em * ($maxwidth / $fontsize); +} + +body { + background-color: $backgroundcolour; + color: $foregroundcolour; + font-family: sans-serif; + margin: 1em; +} + +a:link { color: $linkdefaultcolour; } +a:visited { color: $linkvisitedcolour; } +a:active { color: $linkactivecolour; } + +h1 { @include header_size(60em, 2em); } +h2 { @include header_size(60em, 1.5em); } + +p, dt, dd, li { + text-align: justify; + padding: 0; + margin: 0; +} + +p, div, ul, ol, dl, hr { + max-width: 50em; + padding: 0; + margin: 0; +} + +p, body>div { margin: 1em 0; } + +li { margin: 0 0 0 2em; } +dd { margin: 0 0 0 1em; } + +hr { + clear: both; + margin: 0.5em 0; + border: 0; + border-top: 1px solid $ruledefaultcolour; +} + +kbd { + font-family: monospace; + font-size: 0.95em; + &:before { content: "% "; } +} + +.permalink { + font-size: small; + color: $annotationcolour; + + a:link, a:visited { color: inherit; } +} +@media not screen { + .permalink { visibility: hidden; } +} + +// Site header rules +#breadcrumbs>*, #sitetitle>* { font-size: 0.8em; } +#breadcrumbs { + * { + display: inline; + list-style-type: none; + vertical-align: top; + padding: 0; + margin: 0; + } + + li + li:before { content: "/ "; } +} +#sitetitle * { + display: inline-block; + float: right; +} + +// Site footer rules +#footer { + text-align: center; + max-width: 44em; + padding: 0 3em; + margin: 0; + + p { + color: $annotationcolour; + display: inline-block; + font-size: 0.8em; + max-width: 100%; + margin: 0.2em 0; + } +} + +// "unordered" lists with explicit ordering in content +ul.ordered > { + li { list-style: none; } + li>span:first-child, li>*:first-child>span:first-child { + display: inline-block; + text-align: right; + margin-left: -1.8em; + min-width: 1.8em; + } +} + +@media (max-width: 512px) { + body { margin: 0.6em; } + ul ul { margin-left: -1.2em; } + dd { margin: 0; } +} + +@media (max-width: 35em) { + #sitetitle * { float: none; } + #footer { padding: 0 1em; } +} +@media (max-width: 28em) { + * { text-align: left; } +} diff --git a/lib/css-clean-selectors.rb b/lib/css-clean-selectors.rb new file mode 100644 index 0000000..7eebab7 --- /dev/null +++ b/lib/css-clean-selectors.rb @@ -0,0 +1,53 @@ +# Nick's web site: css_clean_selectors filter. Remove unnecessary whitespace +# from CSS selectors as this improves compatibility with old versions of IE. +# +# Copyright © 2020 Nick Bowler +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +class CssCleanSelectorsFilter < Nanoc::Filter + identifier :css_clean_selectors + + require 'crass' + + def run(content, params = {}) + tree = Crass.parse(content, params) + + queue = Array.new(tree) + while i = queue.shift do + if i[:node] == :at_rule + case i[:name] + when "media", "supports" + # Re-parse the block as a list of rules. + s = Crass::Parser.stringify(i[:block]) + i[:block] = Crass::Parser.parse_rules(s, params) + queue += i[:block] + end + end + + if i[:selector] + ts = i[:selector][:tokens] + ts.each_index do |i| + next if ts[i].nil? or ts[i][:node] != :delim + next if ts[i][:value] == '*' + + ts[i-1] = nil if ts[i-1] and ts[i-1][:node] == :whitespace + ts[i+1] = nil if ts[i+1] and ts[i+1][:node] == :whitespace + end + end + end + + return Crass::Parser.stringify(tree) + end +end diff --git a/lib/css-source.rb b/lib/css-source.rb new file mode 100644 index 0000000..211c155 --- /dev/null +++ b/lib/css-source.rb @@ -0,0 +1,44 @@ +# Nick's web site: css_source filter. Add a notice to generated CSS +# files where the reader may find the source code. +# +# Copyright © 2020 Nick Bowler +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +class CssSourceFilter < Nanoc::Filter + identifier :css_source + + def run(content, params = {}) + srcuri = if params[:uribase] + then params[:uribase] + item_source(@item) end + copypattern = /\/\*.*?[Cc]opyright.*?\*\//m + css = content.gsub(copypattern, "") + css.gsub!(/^@charset.*?$\n?/m, "") + + begin + copymsgs = @item.compiled_content(snapshot: :css_source) + rescue Nanoc::Core::Errors::NoSuchSnapshot + copymsgs = content + end + copymsgs = copymsgs.scan(copypattern) + + ["/*", + " * Generated file, do not edit!", + " * Compiled from " + item_source(@item) + " on " + + Time.now.gmtime.strftime("%Y-%m-%d %H:%M UTC"), + if srcuri then + " * Source code is available online at <" + srcuri + ">" + end, "*/", copymsgs, css].compact.join("\n") + end +end -- 2.43.0