cherry picked changes from Valentin Gagarin
All checks were successful
buildbot/nix-eval Build done.
check / test (push) Successful in 13s
deploy / test (push) Successful in 16s

This commit is contained in:
Luis Hebendanz 2024-07-08 15:35:33 +02:00
parent 3461ee83e0
commit 46b4c704ac
12 changed files with 51 additions and 2681 deletions

View File

@ -1,27 +1,13 @@
# Getting start with the repo
This is the source for the homepage.
We use [zola](https://www.getzola.org/) for building a static website.
## Build the homepage
This will build the website including pages defined in the clan-core repo under `/docs`:
```command
$ nix build
```
This is the source for the Clan homepage.
## Start a local webserver
This server will include all the pages from clan-core, but doesn't automatically refresh. Also make sure to wipe your browsers cache after each change.
```command
$ nix run .#serve
```
## zola build & serve
Alternatively `zola build` and `zola serve` can be used for development but the result will be missing the pages defined in the clan-core repo.
## Contributing
Send changes to https://git.clan.lol/clan/clan-homepage
@ -31,10 +17,3 @@ Send changes to https://git.clan.lol/clan/clan-homepage
```
$ nix run .#deploy
```
## Create a new post
```
$ nix run .#new-post "September Changelog"
```

View File

@ -1,41 +0,0 @@
{
perSystem = {
lib,
pkgs,
self',
...
}: {
apps.new-post.program = builtins.toString (pkgs.writeShellScript "new-post.sh" ''
export PATH="${lib.makeBinPath [
pkgs.coreutils pkgs.gitMinimal
]}"
if [ -z "$1" ]; then
echo "Usage: new-post.sh <title>"
exit 1
fi
title=$(echo "$1" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
root=$(git rev-parse --show-toplevel)
fname="$root/content/blog/$(date +%Y-%m-%d)-$title.md"
if [ -f "$fname" ]; then
echo "File already exists: $fname"
exit 1
fi
cat <<EOF > "$fname"
+++
title = "$1"
date = "$(date --iso-8601=seconds)"
draft = true
template = "blog/page.html"
[taxonomies]
authors = [] # TODO
[extra]
lead = "Some lead"
+++
Some text
EOF
echo "Created $fname"
git add "$fname"
'');
};
}

View File

@ -28,7 +28,7 @@
packages.serve = pkgs.writeShellScriptBin "serve-local" ''
echo "serving: ${self'.packages.website-localhost}"
${pkgs.python3}/bin/python -m http.server 1111 \
-d ${self'.packages.website-localhost}
-d website
'';
};
}

View File

@ -12,7 +12,6 @@
imports = [
./flake-parts/deploy.nix
./flake-parts/devShells
./flake-parts/new-post.nix
./flake-parts/website.nix
];
perSystem = {pkgs, ...}: {

View File

@ -13,18 +13,24 @@
.top-header {
background-color: #2C2C2C;
padding: 1em 0;
width: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 1000;
position: sticky;
z-index: 999;
}
.header-nav-links {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.header-nav-links a {
color: #FFFFFF;
text-decoration: none;
margin: 0 1em;
white-space: nowrap;
padding: 0.5em;
font-size: 1.2em;
}
@ -32,7 +38,6 @@
text-decoration: underline;
}
@media screen and (max-width: 480px) {
.header-nav-links a {
font-size: 1.1em;
@ -150,6 +155,9 @@ section {
body {
line-height: 1;
display: flex;
flex-direction: column;
min-height: 100vh;
}
ol,
@ -210,11 +218,6 @@ html {
box-sizing: inherit;
}
html,
body {
height: 100%;
}
body {
background: #ffffff;
}
@ -248,7 +251,6 @@ a {
-webkit-transition: color 0.2s ease-in-out, border-bottom-color 0.2s ease-in-out;
-ms-transition: color 0.2s ease-in-out, border-bottom-color 0.2s ease-in-out;
transition: color 0.2s ease-in-out, border-bottom-color 0.2s ease-in-out;
border-bottom: dotted 1px;
color: #4eb980;
text-decoration: none;
}
@ -379,22 +381,6 @@ blockquote {
}
@media screen and (max-width: 736px) {
.container {
width: 90% !important;
}
}
@media screen and (max-width: 480px) {
.container {
width: 100% !important;
}
}
/* Row */
.row {
@ -1863,7 +1849,12 @@ blockquote {
}
@media screen and (max-width: 480px) {
@media screen and (max-width: 580px) {
.header-nav-links a:first-child {
flex-basis: 100%;
text-align: center;
}
.row {
display: flex;
@ -2328,6 +2319,21 @@ textarea {
position: relative;
}
.image p {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
text-transform: uppercase;
font-weight: bold;
color: #fff;
background-color: #2C2C2C;
width: 66%;
padding: 0.1em 0.5em 0.1em 0.5em;
}
.image:after {
-moz-transition: opacity 0.25s ease-in-out;
-webkit-transition: opacity 0.25s ease-in-out;
@ -2875,7 +2881,7 @@ input[type="button"].small,
background-repeat: repeat-x, repeat, no-repeat;
background-size: 3200px 460px, auto, cover;
color: rgba(255, 255, 255, 0.8);
padding: 10em 0 20em 0;
padding: 1em 0 10vw 0;
position: relative;
text-align: center;
}
@ -2953,7 +2959,7 @@ input[type="button"].small,
}
#header h1 {
font-size: 2.5em;
font-size: 2vw;
margin: 0;
}
@ -3128,6 +3134,9 @@ input[type="button"].small,
font-size: 14pt;
}
h3 {
font-size: 1.15em;
}
h2 {
font-size: 1.5em;
}
@ -3141,28 +3150,20 @@ input[type="button"].small,
header.major p {
font-size: 1.25em;
}
/* Header */
#header {
padding: 8em 0 16em 0;
}
#header h1 {
font-size: 2.25em;
}
#header p {
font-size: 1.25em;
line-height: 1.65em;
}
}
/* Normal */
@media screen and (max-width: 1280px) {
#header {
padding-bottom: 15vw;
}
#header h1 {
font-size: 4vw;
}
#clan-logo {
width: 14em;
height: 14em;
@ -3224,7 +3225,6 @@ input[type="button"].small,
background-attachment: scroll, scroll, scroll;
background-image: url("images/top-1600.svg"), url("images/overlay.png"), url("../../images/header.jpg");
background-size: 1600px 230px, auto, cover;
padding: 6em 0 12em 0;
}
#header:before {
@ -3235,14 +3235,6 @@ input[type="button"].small,
height: 25px;
}
#header h1 {
font-size: 2em;
}
#header p {
font-size: 1.15em;
}
/* Footer */
#footer {
@ -3292,10 +3284,6 @@ input[type="button"].small,
height: 14em;
}
#header h1 {
font-size: 2em;
}
/* Section/Article */
header.major {
@ -3399,7 +3387,6 @@ input[type="button"].small,
#header {
background-image: url("images/top-1280.svg"), url("images/overlay.png"), url("../../images/header.jpg");
background-size: 1280px 184px, auto, cover;
padding: 3em 0 7em 0;
}
#header:before {
@ -3410,18 +3397,6 @@ input[type="button"].small,
height: 20px;
}
#header .logo {
font-size: 1.5em;
}
#header h1 {
font-size: 1.75em;
}
#header p {
font-size: 1em;
}
/* Footer */
#footer {
@ -3456,10 +3431,6 @@ input[type="button"].small,
height: 10em;
}
#header h1 {
font-size: 1.5em;
}
/* Section/Article */
header.major {
@ -3522,14 +3493,8 @@ input[type="button"].small,
/* Header */
#header {
padding-left: 2em;
padding-right: 2em;
padding-top: 5em;
}
#header br {
display: none;
}
}
}

View File

@ -1,223 +0,0 @@
// breakpoints.scss v1.0 | @ajlkn | MIT licensed */
// Vars.
/// Breakpoints.
/// @var {list}
$breakpoints: () !global;
// Mixins.
/// Sets breakpoints.
/// @param {map} $x Breakpoints.
@mixin breakpoints($x: ()) {
$breakpoints: $x !global;
}
/// Wraps @content in a @media block targeting a specific orientation.
/// @param {string} $orientation Orientation.
@mixin orientation($orientation) {
@media screen and (orientation: #{$orientation}) {
@content;
}
}
/// Wraps @content in a @media block using a given query.
/// @param {string} $query Query.
@mixin breakpoint($query: null) {
$breakpoint: null;
$op: null;
$media: null;
// Determine operator, breakpoint.
// Greater than or equal.
@if (str-slice($query, 0, 2) == '>=') {
$op: 'gte';
$breakpoint: str-slice($query, 3);
}
// Less than or equal.
@elseif (str-slice($query, 0, 2) == '<=') {
$op: 'lte';
$breakpoint: str-slice($query, 3);
}
// Greater than.
@elseif (str-slice($query, 0, 1) == '>') {
$op: 'gt';
$breakpoint: str-slice($query, 2);
}
// Less than.
@elseif (str-slice($query, 0, 1) == '<') {
$op: 'lt';
$breakpoint: str-slice($query, 2);
}
// Not.
@elseif (str-slice($query, 0, 1) == '!') {
$op: 'not';
$breakpoint: str-slice($query, 2);
}
// Equal.
@else {
$op: 'eq';
$breakpoint: $query;
}
// Build media.
@if ($breakpoint and map-has-key($breakpoints, $breakpoint)) {
$a: map-get($breakpoints, $breakpoint);
// Range.
@if (type-of($a) == 'list') {
$x: nth($a, 1);
$y: nth($a, 2);
// Max only.
@if ($x == null) {
// Greater than or equal (>= 0 / anything)
@if ($op == 'gte') {
$media: 'screen';
}
// Less than or equal (<= y)
@elseif ($op == 'lte') {
$media: 'screen and (max-width: ' + $y + ')';
}
// Greater than (> y)
@elseif ($op == 'gt') {
$media: 'screen and (min-width: ' + ($y + 1) + ')';
}
// Less than (< 0 / invalid)
@elseif ($op == 'lt') {
$media: 'screen and (max-width: -1px)';
}
// Not (> y)
@elseif ($op == 'not') {
$media: 'screen and (min-width: ' + ($y + 1) + ')';
}
// Equal (<= y)
@else {
$media: 'screen and (max-width: ' + $y + ')';
}
}
// Min only.
@else if ($y == null) {
// Greater than or equal (>= x)
@if ($op == 'gte') {
$media: 'screen and (min-width: ' + $x + ')';
}
// Less than or equal (<= inf / anything)
@elseif ($op == 'lte') {
$media: 'screen';
}
// Greater than (> inf / invalid)
@elseif ($op == 'gt') {
$media: 'screen and (max-width: -1px)';
}
// Less than (< x)
@elseif ($op == 'lt') {
$media: 'screen and (max-width: ' + ($x - 1) + ')';
}
// Not (< x)
@elseif ($op == 'not') {
$media: 'screen and (max-width: ' + ($x - 1) + ')';
}
// Equal (>= x)
@else {
$media: 'screen and (min-width: ' + $x + ')';
}
}
// Min and max.
@else {
// Greater than or equal (>= x)
@if ($op == 'gte') {
$media: 'screen and (min-width: ' + $x + ')';
}
// Less than or equal (<= y)
@elseif ($op == 'lte') {
$media: 'screen and (max-width: ' + $y + ')';
}
// Greater than (> y)
@elseif ($op == 'gt') {
$media: 'screen and (min-width: ' + ($y + 1) + ')';
}
// Less than (< x)
@elseif ($op == 'lt') {
$media: 'screen and (max-width: ' + ($x - 1) + ')';
}
// Not (< x and > y)
@elseif ($op == 'not') {
$media: 'screen and (max-width: ' + ($x - 1) + '), screen and (min-width: ' + ($y + 1) + ')';
}
// Equal (>= x and <= y)
@else {
$media: 'screen and (min-width: ' + $x + ') and (max-width: ' + $y + ')';
}
}
}
// String.
@else {
// Missing a media type? Prefix with "screen".
@if (str-slice($a, 0, 1) == '(') {
$media: 'screen and ' + $a;
}
// Otherwise, use as-is.
@else {
$media: $a;
}
}
}
// Output.
@media #{$media} {
@content;
}
}

View File

@ -1,90 +0,0 @@
/// Removes a specific item from a list.
/// @author Hugo Giraudel
/// @param {list} $list List.
/// @param {integer} $index Index.
/// @return {list} Updated list.
@function remove-nth($list, $index) {
$result: null;
@if type-of($index) != number {
@warn "$index: #{quote($index)} is not a number for `remove-nth`.";
}
@else if $index == 0 {
@warn "List index 0 must be a non-zero integer for `remove-nth`.";
}
@else if abs($index) > length($list) {
@warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`.";
}
@else {
$result: ();
$index: if($index < 0, length($list) + $index + 1, $index);
@for $i from 1 through length($list) {
@if $i != $index {
$result: append($result, nth($list, $i));
}
}
}
@return $result;
}
/// Gets a value from a map.
/// @author Hugo Giraudel
/// @param {map} $map Map.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function val($map, $keys...) {
@if nth($keys, 1) == null {
$keys: remove-nth($keys, 1);
}
@each $key in $keys {
$map: map-get($map, $key);
}
@return $map;
}
/// Gets a duration value.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function _duration($keys...) {
@return val($duration, $keys...);
}
/// Gets a font value.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function _font($keys...) {
@return val($font, $keys...);
}
/// Gets a misc value.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function _misc($keys...) {
@return val($misc, $keys...);
}
/// Gets a palette value.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function _palette($keys...) {
@return val($palette, $keys...);
}
/// Gets a size value.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function _size($keys...) {
@return val($size, $keys...);
}

View File

@ -1,149 +0,0 @@
// html-grid.scss v1.0 | @ajlkn | MIT licensed */
// Mixins.
/// Initializes the current element as an HTML grid.
/// @param {mixed} $gutters Gutters (either a single number to set both column/row gutters, or a list to set them individually).
/// @param {mixed} $suffix Column class suffix (optional; either a single suffix or a list).
@mixin html-grid($gutters: 1.5em, $suffix: '') {
// Initialize.
$cols: 12;
$multipliers: 0, 0.25, 0.5, 1, 1.50, 2.00;
$unit: 100% / $cols;
// Suffixes.
$suffixes: null;
@if (type-of($suffix) == 'list') {
$suffixes: $suffix;
}
@else {
$suffixes: ($suffix);
}
// Gutters.
$guttersCols: null;
$guttersRows: null;
@if (type-of($gutters) == 'list') {
$guttersCols: nth($gutters, 1);
$guttersRows: nth($gutters, 2);
}
@else {
$guttersCols: $gutters;
$guttersRows: 0;
}
// Row.
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
align-items: stretch;
// Columns.
> * {
box-sizing: border-box;
}
// Gutters.
&.gtr-uniform {
> * {
> :last-child {
margin-bottom: 0;
}
}
}
// Alignment.
&.aln-left {
justify-content: flex-start;
}
&.aln-center {
justify-content: center;
}
&.aln-right {
justify-content: flex-end;
}
&.aln-top {
align-items: flex-start;
}
&.aln-middle {
align-items: center;
}
&.aln-bottom {
align-items: flex-end;
}
// Step through suffixes.
@each $suffix in $suffixes {
// Suffix.
@if ($suffix != '') {
$suffix: '-' + $suffix;
}
@else {
$suffix: '';
}
// Row.
// Important.
> .imp#{$suffix} {
order: -1;
}
// Columns, offsets.
@for $i from 1 through $cols {
> .col-#{$i}#{$suffix} {
width: $unit * $i;
}
> .off-#{$i}#{$suffix} {
margin-left: $unit * $i;
}
}
// Step through multipliers.
@each $multiplier in $multipliers {
// Gutters.
$class: null;
@if ($multiplier != 1) {
$class: '.gtr-' + ($multiplier * 100);
}
&#{$class} {
margin-top: ($guttersRows * $multiplier * -1);
margin-left: ($guttersCols * $multiplier * -1);
> * {
padding: ($guttersRows * $multiplier) 0 0 ($guttersCols * $multiplier);
}
// Uniform.
&.gtr-uniform {
margin-top: $guttersCols * $multiplier * -1;
> * {
padding-top: $guttersCols * $multiplier;
}
}
}
}
}
}

View File

@ -1,78 +0,0 @@
/// Makes an element's :before pseudoelement a FontAwesome icon.
/// @param {string} $content Optional content value to use.
/// @param {string} $category Optional category to use.
/// @param {string} $where Optional pseudoelement to target (before or after).
@mixin icon($content: false, $category: regular, $where: before) {
text-decoration: none;
&:#{$where} {
@if $content {
content: $content;
}
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-style: normal;
font-variant: normal;
text-rendering: auto;
line-height: 1;
text-transform: none !important;
@if ($category == brands) {
font-family: 'Font Awesome 5 Brands';
}
@elseif ($category == solid) {
font-family: 'Font Awesome 5 Free';
font-weight: 900;
}
@else {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
}
}
/// Applies padding to an element, taking the current element-margin value into account.
/// @param {mixed} $tb Top/bottom padding.
/// @param {mixed} $lr Left/right padding.
/// @param {list} $pad Optional extra padding (in the following order top, right, bottom, left)
/// @param {bool} $important If true, adds !important.
@mixin padding($tb, $lr, $pad: (0,0,0,0), $important: null) {
@if $important {
$important: '!important';
}
$x: 0.1em;
@if unit(_size(element-margin)) == 'rem' {
$x: 0.1rem;
}
padding: ($tb + nth($pad,1)) ($lr + nth($pad,2)) max($x, $tb - _size(element-margin) + nth($pad,3)) ($lr + nth($pad,4)) #{$important};
}
/// Encodes a SVG data URL so IE doesn't choke (via codepen.io/jakob-e/pen/YXXBrp).
/// @param {string} $svg SVG data URL.
/// @return {string} Encoded SVG data URL.
@function svg-url($svg) {
$svg: str-replace($svg, '"', '\'');
$svg: str-replace($svg, '%', '%25');
$svg: str-replace($svg, '<', '%3C');
$svg: str-replace($svg, '>', '%3E');
$svg: str-replace($svg, '&', '%26');
$svg: str-replace($svg, '#', '%23');
$svg: str-replace($svg, '{', '%7B');
$svg: str-replace($svg, '}', '%7D');
$svg: str-replace($svg, ';', '%3B');
@return url("data:image/svg+xml;charset=utf8,#{$svg}");
}

View File

@ -1,41 +0,0 @@
// Misc.
$misc: (
);
// Duration.
$duration: (
);
// Size.
$size: (
border-radius: 4px
);
// Font.
$font: (
);
// Palette.
$palette: (
bg: #ffffff,
fg: #6e6e6e,
fg-light: #888888,
fg-bold: #5b5b5b,
border: rgba(224,224,224,0.75),
border-bg: rgba(224,224,224,0.15),
border-bg2: rgba(224,224,224,0.35),
accent1: (
bg: #4eb980,
fg: rgba(255,255,255,0.8),
fg-light: rgba(255,255,255,0.5),
fg-bold: #ffffff
),
accent2: (
bg: #544d55,
fg: rgba(255,255,255,0.8),
fg-light: rgba(255,255,255,0.35),
fg-bold: #ffffff
)
);

View File

@ -1,376 +0,0 @@
// vendor.scss v1.0 | @ajlkn | MIT licensed */
// Vars.
/// Vendor prefixes.
/// @var {list}
$vendor-prefixes: (
'-moz-',
'-webkit-',
'-ms-',
''
);
/// Properties that should be vendorized.
/// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org
/// @var {list}
$vendor-properties: (
// Animation.
'animation',
'animation-delay',
'animation-direction',
'animation-duration',
'animation-fill-mode',
'animation-iteration-count',
'animation-name',
'animation-play-state',
'animation-timing-function',
// Appearance.
'appearance',
// Backdrop filter.
'backdrop-filter',
// Background image options.
'background-clip',
'background-origin',
'background-size',
// Box sizing.
'box-sizing',
// Clip path.
'clip-path',
// Filter effects.
'filter',
// Flexbox.
'align-content',
'align-items',
'align-self',
'flex',
'flex-basis',
'flex-direction',
'flex-flow',
'flex-grow',
'flex-shrink',
'flex-wrap',
'justify-content',
'order',
// Font feature.
'font-feature-settings',
'font-language-override',
'font-variant-ligatures',
// Font kerning.
'font-kerning',
// Fragmented borders and backgrounds.
'box-decoration-break',
// Grid layout.
'grid-column',
'grid-column-align',
'grid-column-end',
'grid-column-start',
'grid-row',
'grid-row-align',
'grid-row-end',
'grid-row-start',
'grid-template-columns',
'grid-template-rows',
// Hyphens.
'hyphens',
'word-break',
// Masks.
'mask',
'mask-border',
'mask-border-outset',
'mask-border-repeat',
'mask-border-slice',
'mask-border-source',
'mask-border-width',
'mask-clip',
'mask-composite',
'mask-image',
'mask-origin',
'mask-position',
'mask-repeat',
'mask-size',
// Multicolumn.
'break-after',
'break-before',
'break-inside',
'column-count',
'column-fill',
'column-gap',
'column-rule',
'column-rule-color',
'column-rule-style',
'column-rule-width',
'column-span',
'column-width',
'columns',
// Object fit.
'object-fit',
'object-position',
// Regions.
'flow-from',
'flow-into',
'region-fragment',
// Scroll snap points.
'scroll-snap-coordinate',
'scroll-snap-destination',
'scroll-snap-points-x',
'scroll-snap-points-y',
'scroll-snap-type',
// Shapes.
'shape-image-threshold',
'shape-margin',
'shape-outside',
// Tab size.
'tab-size',
// Text align last.
'text-align-last',
// Text decoration.
'text-decoration-color',
'text-decoration-line',
'text-decoration-skip',
'text-decoration-style',
// Text emphasis.
'text-emphasis',
'text-emphasis-color',
'text-emphasis-position',
'text-emphasis-style',
// Text size adjust.
'text-size-adjust',
// Text spacing.
'text-spacing',
// Transform.
'transform',
'transform-origin',
// Transform 3D.
'backface-visibility',
'perspective',
'perspective-origin',
'transform-style',
// Transition.
'transition',
'transition-delay',
'transition-duration',
'transition-property',
'transition-timing-function',
// Unicode bidi.
'unicode-bidi',
// User select.
'user-select',
// Writing mode.
'writing-mode',
);
/// Values that should be vendorized.
/// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org
/// @var {list}
$vendor-values: (
// Cross fade.
'cross-fade',
// Element function.
'element',
// Filter function.
'filter',
// Flexbox.
'flex',
'inline-flex',
// Grab cursors.
'grab',
'grabbing',
// Gradients.
'linear-gradient',
'repeating-linear-gradient',
'radial-gradient',
'repeating-radial-gradient',
// Grid layout.
'grid',
'inline-grid',
// Image set.
'image-set',
// Intrinsic width.
'max-content',
'min-content',
'fit-content',
'fill',
'fill-available',
'stretch',
// Sticky position.
'sticky',
// Transform.
'transform',
// Zoom cursors.
'zoom-in',
'zoom-out',
);
// Functions.
/// Removes a specific item from a list.
/// @author Hugo Giraudel
/// @param {list} $list List.
/// @param {integer} $index Index.
/// @return {list} Updated list.
@function remove-nth($list, $index) {
$result: null;
@if type-of($index) != number {
@warn "$index: #{quote($index)} is not a number for `remove-nth`.";
}
@else if $index == 0 {
@warn "List index 0 must be a non-zero integer for `remove-nth`.";
}
@else if abs($index) > length($list) {
@warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`.";
}
@else {
$result: ();
$index: if($index < 0, length($list) + $index + 1, $index);
@for $i from 1 through length($list) {
@if $i != $index {
$result: append($result, nth($list, $i));
}
}
}
@return $result;
}
/// Replaces a substring within another string.
/// @author Hugo Giraudel
/// @param {string} $string String.
/// @param {string} $search Substring.
/// @param {string} $replace Replacement.
/// @return {string} Updated string.
@function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}
/// Replaces a substring within each string in a list.
/// @param {list} $strings List of strings.
/// @param {string} $search Substring.
/// @param {string} $replace Replacement.
/// @return {list} Updated list of strings.
@function str-replace-all($strings, $search, $replace: '') {
@each $string in $strings {
$strings: set-nth($strings, index($strings, $string), str-replace($string, $search, $replace));
}
@return $strings;
}
// Mixins.
/// Wraps @content in vendorized keyframe blocks.
/// @param {string} $name Name.
@mixin keyframes($name) {
@-moz-keyframes #{$name} { @content; }
@-webkit-keyframes #{$name} { @content; }
@-ms-keyframes #{$name} { @content; }
@keyframes #{$name} { @content; }
}
/// Vendorizes a declaration's property and/or value(s).
/// @param {string} $property Property.
/// @param {mixed} $value String/list of value(s).
@mixin vendor($property, $value) {
// Determine if property should expand.
$expandProperty: index($vendor-properties, $property);
// Determine if value should expand (and if so, add '-prefix-' placeholder).
$expandValue: false;
@each $x in $value {
@each $y in $vendor-values {
@if $y == str-slice($x, 1, str-length($y)) {
$value: set-nth($value, index($value, $x), '-prefix-' + $x);
$expandValue: true;
}
}
}
// Expand property?
@if $expandProperty {
@each $vendor in $vendor-prefixes {
#{$vendor}#{$property}: #{str-replace-all($value, '-prefix-', $vendor)};
}
}
// Expand just the value?
@elseif $expandValue {
@each $vendor in $vendor-prefixes {
#{$property}: #{str-replace-all($value, '-prefix-', $vendor)};
}
}
// Neither? Treat them as a normal declaration.
@else {
#{$property}: #{$value};
}
}

File diff suppressed because it is too large Load Diff