Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 138a3c3342 | |||
| fc28e8c5c8 | |||
| d67c7fc926 | |||
| 8a9b36d3db | |||
| deea763923 | |||
| 8f34df0cbd | |||
| 87f6da2957 | |||
| 766fee12d5 | |||
| 6488bed03c | |||
| ea7092ebef | |||
| ac79051db4 | |||
| 1194223ddd | |||
| ad76f6fb7a | |||
| f39a05ba59 | |||
| 67f20f4379 | |||
| 2c857250c0 | |||
| 931b6e0208 | |||
| 8ea9ca2b2f | |||
| 9def31abeb | |||
| 1878d023bf | |||
| fef327ec61 | |||
| 5ddd86e4aa | |||
| 87dd96adbd | |||
| 9de0095c8d | |||
| 7480da7568 | |||
| 81c65b3cce | |||
| 441c05f096 | |||
| 671573bc2e | |||
| 17b0bea213 | |||
| 0ad96058d5 | |||
| 092efca34d | |||
| 0303019641 | |||
| 8efff11ac2 | |||
| 4a6f8d90d8 | |||
| b572d957fc | |||
| 0f70fc7bf0 | |||
| a38b0dbea5 | |||
| 42f4bca8ba | |||
| 2f254fd355 | |||
| f54c388b1a | |||
| ee66a10fc3 | |||
| d52f58ecae | |||
| 376745b825 | |||
| 1c432afdbf | |||
| df731a8171 | |||
| 503bdbd527 | |||
| 8b153119ea | |||
| de3e1f1210 | |||
| e693abc079 | |||
| 72bf8d9410 | |||
| 8736cc97b4 | |||
| 2eac27a439 | |||
| bbbfba2e8f | |||
| 97c06514eb | |||
| 4c3e285547 | |||
| 40a86b41c7 | |||
| 301d81a637 | |||
| dc260a27d6 | |||
| 6801e99164 | |||
| e672d60008 | |||
| a87bfdf687 | |||
| 79c07edb4d | |||
| 542453939e | |||
| 84d24471b2 | |||
| 3a8891979a | |||
| 4d37930689 | |||
| 1a0251071d | |||
| d440ccc1b3 | |||
| bf7b18fd1f | |||
| 4c43510c44 | |||
| 73a5044ef2 | |||
| 6d8c943976 | |||
| 32cbbebe97 | |||
| 85ec3ee5c9 | |||
| ff6d4f242b | |||
| a78cf9f6bb | |||
| 80d95d09f9 | |||
| 7942000d96 | |||
| 6d2160aa26 | |||
| 9c9f514752 | |||
| e732aa8b10 |
@@ -1,2 +1,6 @@
|
|||||||
wwwroot/*
|
mode:regex
|
||||||
nbproject/*
|
^_dist/
|
||||||
|
^sites/[^/]+/data/
|
||||||
|
^sites/[^/]+/wwwroot/
|
||||||
|
|
||||||
|
^shields_cache/
|
||||||
|
|||||||
3
.hgtags
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
42a17645b5b21d7fe395767de7fa3e26ee999014 release-r54
|
||||||
|
0f89ae041c2ee60cc1ea308d047fce816b19c490 release-r64
|
||||||
|
d4733a95c3428db8722ce0d0350d17bbbabc8720 release-r72
|
||||||
8
TODO.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
- Merge "written in" and "tags"
|
||||||
|
|
||||||
|
- RSS for recent changes
|
||||||
|
|
||||||
|
- RSS for all projects
|
||||||
|
|
||||||
|
- Switchable CSS (reddit theme, 4chan theme, HN theme)
|
||||||
46
_dist/README.txt
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
A static site generator for a portfolio website.
|
||||||
|
|
||||||
|
The scripts used to generate the code.ivysaur.me website.
|
||||||
|
|
||||||
|
Written in PHP, Bash
|
||||||
|
|
||||||
|
=FEATURES=
|
||||||
|
|
||||||
|
- Generates static website, minimising server load and decreasing attack surface compared to dynamic server-side PHP
|
||||||
|
- Automatic thumbnailing and sprite sheet generation
|
||||||
|
- Download file attachments per-project
|
||||||
|
- One-click rebuild, one-click deploy
|
||||||
|
- Parallel generation
|
||||||
|
|
||||||
|
=CHANGELOG=
|
||||||
|
|
||||||
|
2015-04-05: r72
|
||||||
|
- Feature: Support redirecting old project names
|
||||||
|
- Feature: Add file hash in download URLs to prevent filename collisions
|
||||||
|
- Fix an issue generating spritesheets even if no project images are present
|
||||||
|
- Don't include `ctime` when estimating project update time
|
||||||
|
|
||||||
|
2015-04-05: r64
|
||||||
|
- Feature: Support sorting projects
|
||||||
|
|
||||||
|
2015-04-04: r54
|
||||||
|
- Feature: Support multiple code sites
|
||||||
|
- Fix an issue with parallel builds on some versions of windows
|
||||||
|
- Fix an issue corrupting URL links with multiple parameters
|
||||||
|
- Fix a cosmetic issue with page overflow
|
||||||
|
- Fix a cosmetic issue with whitespace on code elements
|
||||||
|
|
||||||
|
2014-07-02: r39
|
||||||
|
- Feature: Tags
|
||||||
|
- Feature: Generate pages in parallel
|
||||||
|
- Enhancement: Support raw HTML sections in page content
|
||||||
|
- Fix an issue with URLs containing spaces
|
||||||
|
- Fix a cosmetic issue with image thumbnail backgrounds
|
||||||
|
- Fix a cosmetic issue with download sort order
|
||||||
|
- Fix a cosmetic issue with page layout
|
||||||
|
|
||||||
|
2013-09-28: r13
|
||||||
|
- Initial public source code release
|
||||||
|
|
||||||
|
2013-09-21: r3
|
||||||
|
- Initial deployment
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
start C:\bin\cygwin\bin\mintty.exe /bin/bash -l -c "rsync -avz -e ""ssh -i /cygdrive/c/www/ms1_deploy_key -p 2222"" --progress /cygdrive/c/www/m6/code/wwwroot www-data@ms1.ivysaur.me:~/code.ivysaur.me/"
|
|
||||||
16
deploy.sh
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
LOCALDIR=/cygdrive/c/www/m6/code/sites/code.ivysaur.me/wwwroot
|
||||||
|
|
||||||
|
chmod -R 644 "$LOCALDIR"
|
||||||
|
chmod -R a+X "$LOCALDIR"
|
||||||
|
|
||||||
|
rsync --delete -avz -e "ssh -i /cygdrive/c/www/ms1_deploy_key -p 2222" --progress \
|
||||||
|
"$LOCALDIR" \
|
||||||
|
www-data@ms1.ivysaur.me:~/code.ivysaur.me/
|
||||||
|
|
||||||
|
# n.b. set chmod -R a+rX remote side?
|
||||||
|
|
||||||
|
read -p "Press any key to continue..."
|
||||||
9
mkdist.sh
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
tar cJvf "codesite-$(date +%s).tar.xz" \
|
||||||
|
rebuild.php rebuild.sh sites/codesite.example.com static_global \
|
||||||
|
--owner=0 --group=0
|
||||||
|
|
||||||
|
read -p "Press any key to continue..."
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
@echo off
|
|
||||||
C:\bin\php54\php.exe rebuild.php
|
|
||||||
pause
|
|
||||||
408
rebuild.php
@@ -3,15 +3,20 @@
|
|||||||
// Code-hosting website
|
// Code-hosting website
|
||||||
// ````````````````````
|
// ````````````````````
|
||||||
|
|
||||||
// CONFIGURATION
|
function mkshield($left_str, $right_str, $color_str) {
|
||||||
// `````````````
|
$filename = rawurlencode(str_replace('-', '--', $left_str)).'-'.rawurlencode(str_replace('-', '--', $right_str)).'-'.rawurlencode($color_str).'.svg';
|
||||||
|
$cache_path = __DIR__.'/../../shields_cache/'.$filename;
|
||||||
define('BASEDIR', __DIR__.'\\');
|
|
||||||
define('SITE_TITLE', 'code.ivysaur.me');
|
if (file_exists($cache_path)) {
|
||||||
define('PAGE_THUMB_W', 60);
|
return file_get_contents($cache_path);
|
||||||
define('PAGE_THUMB_H', 60);
|
|
||||||
define('INDEX_THUMB_W', 90);
|
} else {
|
||||||
define('INDEX_THUMB_H', 32); // recommend a multiple of the jpg iDCT block size
|
$retn = file_get_contents('https://img.shields.io/badge/'.$filename);
|
||||||
|
file_put_contents($cache_path, $retn);
|
||||||
|
return $retn;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a thumbnail of an image. It overscales, centers, and crops to fit the
|
* Create a thumbnail of an image. It overscales, centers, and crops to fit the
|
||||||
@@ -29,6 +34,7 @@ function mkthumbnail($src_file, $dest_file, $width, $height) {
|
|||||||
$im = imagecreatefromstring(file_get_contents($src_file));
|
$im = imagecreatefromstring(file_get_contents($src_file));
|
||||||
|
|
||||||
$dest = imagecreatetruecolor($width, $height);
|
$dest = imagecreatetruecolor($width, $height);
|
||||||
|
imagefilledrectangle($dest, 0, 0, $width, $height, imagecolorallocate($dest, 0xFF, 0xFF, 0xFF));
|
||||||
|
|
||||||
$scale = max( $width/$src_width, $height/$src_height ); // overscale + crop
|
$scale = max( $width/$src_width, $height/$src_height ); // overscale + crop
|
||||||
|
|
||||||
@@ -68,25 +74,6 @@ function mkspritesheet(array $handles, $dest_file, $width, $height) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a directory tree and all its contents.
|
|
||||||
*
|
|
||||||
* @author http://www.php.net/manual/en/function.rmdir.php#110489
|
|
||||||
* @param string $dir
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
function rmdir_recursive($dir) {
|
|
||||||
$files = array_diff(scandir($dir), array('.','..'));
|
|
||||||
foreach ($files as $file) {
|
|
||||||
if (is_dir("$dir/$file")) {
|
|
||||||
rmdir_recursive("$dir/$file");
|
|
||||||
} else {
|
|
||||||
unlink("$dir/$file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rmdir($dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
function fbytes($size, $suffixes='B|KiB|MiB|GiB|TiB') {
|
function fbytes($size, $suffixes='B|KiB|MiB|GiB|TiB') {
|
||||||
$sxlist = explode('|', $suffixes);
|
$sxlist = explode('|', $suffixes);
|
||||||
if ($size < 1024) {
|
if ($size < 1024) {
|
||||||
@@ -114,20 +101,69 @@ function hesc($sz) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function text2html($sz) {
|
function text2html($sz) {
|
||||||
$base = hesc($sz);
|
|
||||||
$base = preg_replace('~(https?://[^ \\r\\n\\t]+)~i', '<a href="\\1">\\1</a>', $base);
|
$identity = function($sz) {
|
||||||
|
return $sz;
|
||||||
|
};
|
||||||
|
|
||||||
$base = preg_replace('~=+(.+)=+~', '<strong>\\1</strong>', $base);
|
$splitInside = function($begin, $end, $sz) {
|
||||||
|
$parts = explode($begin, $sz);
|
||||||
$btparts = explode('`', $base);
|
if (count($parts) == 1) return [$sz];
|
||||||
if (count($btparts) > 1 && (count($btparts) % 2)) {
|
|
||||||
for ($i = 1, $e = count($btparts); $i < $e; $i += 2) {
|
$ret = [$parts[0]];
|
||||||
$btparts[$i] = '<span class="code">'.$btparts[$i].'</span>';
|
for($i = 1, $e = count($parts); $i !== $e; ++$i) {
|
||||||
|
$inner = explode($end, $parts[$i], 2);
|
||||||
|
$ret = array_merge($ret, $inner);
|
||||||
}
|
}
|
||||||
$base = implode('', $btparts);
|
return $ret;
|
||||||
}
|
};
|
||||||
|
|
||||||
return nl2br($base);
|
$oddEven = function(array $parts, $odd, $even, $join='') {
|
||||||
|
$ret = [];
|
||||||
|
for($i = 0, $e = count($parts); $i != $e; ++$i) {
|
||||||
|
$ret[] = ($i % 2) ? $odd($parts[$i]) : $even($parts[$i]);
|
||||||
|
}
|
||||||
|
return implode($join, $ret);
|
||||||
|
};
|
||||||
|
|
||||||
|
$sectionFmt = function($sz) use($oddEven, $identity) {
|
||||||
|
$base = hesc($sz);
|
||||||
|
|
||||||
|
$base = preg_replace('~^=+(.+)=+~m', '<strong>\\1</strong>', $base);
|
||||||
|
$base = preg_replace('~(https?://[^ \\r\\n\\t]+)~i', '<a href="\\1">\\1</a>', $base);
|
||||||
|
$base = preg_replace('~\\[b\\](.+?)\\[/b\\]~m', '<strong>\\1</strong>', $base);
|
||||||
|
$base = preg_replace('~\\[i\\](.+?)\\[/i\\]~m', '<i>\\1</i>', $base);
|
||||||
|
$base = preg_replace('~\\[spoiler\\](.+?)\\[/spoiler\\]~m', '<span class="spoiler">\\1</span>', $base);
|
||||||
|
$base = preg_replace('~\\[entry=([^\\]]+?)\\](.+?)\\[/entry\\]~m', '<a href="\\1.html">\\2</a>', $base);
|
||||||
|
$base = preg_replace('~\n- ~ms', "\n• ", $base);
|
||||||
|
|
||||||
|
$btparts = explode('`', $base);
|
||||||
|
if (count($btparts) > 1 && (count($btparts) % 2)) {
|
||||||
|
for ($i = 1, $e = count($btparts); $i < $e; $i += 2) {
|
||||||
|
$class = 'code';
|
||||||
|
if (strpos($btparts[$i], "\n") !== false) {
|
||||||
|
$class .= ' code-multiline';
|
||||||
|
}
|
||||||
|
$btparts[$i] = '<span class="'.$class.'">'.$btparts[$i].'</span>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $oddEven($btparts, $identity, 'nl2br');
|
||||||
|
};
|
||||||
|
|
||||||
|
$htmlSections = $splitInside('<html>', '</html>', $sz);
|
||||||
|
return $oddEven($htmlSections, $identity, $sectionFmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
function array_decimate($array, $total, $partno) {
|
||||||
|
$ct = 0;
|
||||||
|
$ret = [];
|
||||||
|
foreach($array as $k => $v) {
|
||||||
|
if (++$ct % $total == ($partno - 1)) {
|
||||||
|
$ret[$k] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,9 +175,13 @@ class CProject {
|
|||||||
public $projname;
|
public $projname;
|
||||||
public $shortdesc = '(no description)';
|
public $shortdesc = '(no description)';
|
||||||
public $subtag = '';
|
public $subtag = '';
|
||||||
|
public $lastupdate = 0;
|
||||||
private $longdesc = '';
|
private $longdesc = '';
|
||||||
|
private $prefix_html = '';
|
||||||
private $images = array();
|
private $images = array();
|
||||||
private $downloads = array();
|
private $downloads = array();
|
||||||
|
private $downloads_hashes = array();
|
||||||
|
public $tags = array();
|
||||||
|
|
||||||
public $homeimage = null;
|
public $homeimage = null;
|
||||||
|
|
||||||
@@ -152,27 +192,93 @@ class CProject {
|
|||||||
// Identify resources in folder
|
// Identify resources in folder
|
||||||
|
|
||||||
$ls = scandir($this->dir);
|
$ls = scandir($this->dir);
|
||||||
|
$found_real_lastupdate = false;
|
||||||
foreach($ls as $file) {
|
foreach($ls as $file) {
|
||||||
if ($file[0] == '.') continue;
|
if ($file[0] == '.') continue;
|
||||||
|
|
||||||
if ($file == 'README.txt') {
|
if ($file == 'README.txt') {
|
||||||
|
|
||||||
|
// Guess 'last update' time
|
||||||
|
$matches = [];
|
||||||
|
if (preg_match('~\n(\d\d\d\d-\d\d-\d\d)~', $this->longdesc, $matches)) {
|
||||||
|
// Use first date entry (assumed to be a CHANGELOG)
|
||||||
|
$this->lastupdate = strtotime($matches[1]);
|
||||||
|
$found_real_lastupdate = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
$this->longdesc = file_get_contents($this->dir.'README.txt');
|
$this->longdesc = file_get_contents($this->dir.'README.txt');
|
||||||
|
|
||||||
$matches = array();
|
$matches = array();
|
||||||
if (preg_match('~Written in ([^\\r\\n]+)~', $this->longdesc, $matches)) {
|
if (preg_match('~Written in ([^\\r\\n]+)~', $this->longdesc, $matches)) {
|
||||||
$this->subtag = rtrim($matches[1], ' .');
|
$this->subtag = rtrim($matches[1], ' .');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->shortdesc = array_shift(explode("\n", $this->longdesc));
|
if (preg_match('~Tags: ([^\\r\\n]+)~', $this->longdesc, $matches)) {
|
||||||
|
$this->tags = array_map('trim', explode(',', $matches[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
$parts = explode("\n", $this->longdesc);
|
||||||
|
$this->shortdesc = array_shift($parts);
|
||||||
$this->shortdesc[0] = strtolower($this->shortdesc[0]); // cosmetic lowercase
|
$this->shortdesc[0] = strtolower($this->shortdesc[0]); // cosmetic lowercase
|
||||||
|
|
||||||
|
// Filter longdesc
|
||||||
|
$this->longdesc = str_replace("\r", "", $this->longdesc); // filter windows CR
|
||||||
|
|
||||||
|
$prefix_html = '';
|
||||||
|
$this->longdesc = preg_replace_callback('~\r?\nWritten in ([^\\n]+)~ms', function($matches) use (&$prefix_html) {
|
||||||
|
$prefix_html .= (
|
||||||
|
(SHIELDS_PREFIX ? mkshield('build', 'success', 'brightgreen').' ' : '').
|
||||||
|
mkshield('written in', $matches[1], 'blue')
|
||||||
|
);
|
||||||
|
return '';
|
||||||
|
}, $this->longdesc);
|
||||||
|
|
||||||
|
while(strpos($this->longdesc, "\n\n\n") !== false) {
|
||||||
|
$this->longdesc = str_replace("\n\n\n", "\n\n", $this->longdesc);
|
||||||
|
}
|
||||||
|
$this->longdesc = rtrim($this->longdesc, "\n");
|
||||||
|
|
||||||
|
$this->prefix_html = $prefix_html;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! $found_real_lastupdate) {
|
||||||
|
$this->lastupdate = max(
|
||||||
|
$this->lastupdate,
|
||||||
|
// filectime($this->dir.$file),
|
||||||
|
($file == 'README.txt' ? filectime($this->dir.$file) : filemtime($this->dir.$file)) // Don't count README updates
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_image($file)) {
|
if (is_image($file)) {
|
||||||
$this->images[] = $file;
|
$this->images[] = $file;
|
||||||
} else {
|
} else {
|
||||||
$this->downloads[] = $file;
|
$this->downloads[] = $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
natcasesort($this->downloads);
|
||||||
|
$this->downloads = array_reverse($this->downloads);
|
||||||
|
|
||||||
|
for($i = 0, $e = count($this->downloads); $i !== $e; ++$i) {
|
||||||
|
$this->downloads_hashes[] = (
|
||||||
|
sha1_file($this->dir.$this->downloads[$i])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function genHomeImage() {
|
||||||
|
if (count($this->images)) {
|
||||||
|
|
||||||
|
$this->homeimage = mkthumbnail(
|
||||||
|
$this->dir.$this->images[0],
|
||||||
|
null, // raw handle
|
||||||
|
INDEX_THUMB_W, INDEX_THUMB_H
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function write() {
|
public function write() {
|
||||||
@@ -186,18 +292,24 @@ class CProject {
|
|||||||
mkthumbnail($outfile.'.'.str_ext($image), $outfile.'_thumb.jpg', PAGE_THUMB_W, PAGE_THUMB_H);
|
mkthumbnail($outfile.'.'.str_ext($image), $outfile.'_thumb.jpg', PAGE_THUMB_W, PAGE_THUMB_H);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($this->images)) {
|
|
||||||
$this->homeimage = mkthumbnail(
|
|
||||||
BASEDIR.'wwwroot/srv/'.$this->projname.'_0.'.str_ext($this->images[0]),
|
|
||||||
null, // raw handle
|
|
||||||
INDEX_THUMB_W, INDEX_THUMB_H
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy downloads to wwwroot
|
// Copy downloads to wwwroot
|
||||||
|
|
||||||
foreach($this->downloads as $idx => $filename) {
|
foreach($this->downloads as $idx => $filename) {
|
||||||
copy($this->dir.$filename, BASEDIR.'wwwroot/srv/'.$filename);
|
$cmkdir = @mkdir( BASEDIR.'wwwroot/srv/'.$this->downloads_hashes[$idx] );
|
||||||
|
|
||||||
|
if (! $cmkdir) {
|
||||||
|
fputs(
|
||||||
|
STDOUT,
|
||||||
|
"WARNING: Couldn't create directory ".$this->downloads_hashes[$idx].
|
||||||
|
" for file '${filename}'".
|
||||||
|
" in project '".$this->projname."'!\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(
|
||||||
|
$this->dir.$filename,
|
||||||
|
BASEDIR.'wwwroot/srv/'.$this->downloads_hashes[$idx].'/'.$filename
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate index page
|
// Generate index page
|
||||||
@@ -208,28 +320,42 @@ class CProject {
|
|||||||
file_put_contents(BASEDIR.'wwwroot/'.$this->projname.'.html', $idxfile);
|
file_put_contents(BASEDIR.'wwwroot/'.$this->projname.'.html', $idxfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getClassAttr() {
|
||||||
|
if (count($this->tags)) {
|
||||||
|
return 'taggedWith-'.implode(' taggedWith-', $this->tags);
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
?>
|
?>
|
||||||
<h2><?=hesc($this->projname)?></h2>
|
<h2><?=hesc(str_replace('_', ' ', $this->projname))?></h2>
|
||||||
|
|
||||||
<div class="projinfo">
|
<div class="projinfo">
|
||||||
|
|
||||||
<div class="projbody projbody_<?=(count($this->images) ? 'half' : 'full')?>w">
|
<div class="projbody projbody_<?=(count($this->images) ? 'half' : 'full')?>w">
|
||||||
|
|
||||||
<strong>ABOUT</strong>
|
<?php if (strlen($this->prefix_html)) { ?>
|
||||||
|
<p style="margin-top:0;"><?=$this->prefix_html?></p>
|
||||||
|
<?php } ?>
|
||||||
|
|
||||||
|
<strong><?=hesc(strtoupper(ARTICLE_HEADER))?></strong>
|
||||||
|
|
||||||
<p><?=text2html($this->longdesc)?></p>
|
<p><?=text2html($this->longdesc)?></p>
|
||||||
|
|
||||||
|
<?=file_get_contents(BASEDIR.'/footer.htm')?>
|
||||||
|
|
||||||
<?php if (count($this->downloads)) { ?>
|
<?php if (count($this->downloads)) { ?>
|
||||||
|
|
||||||
<strong>DOWNLOAD</strong>
|
<strong>DOWNLOAD</strong>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<?php foreach($this->downloads as $filename) { ?>
|
<?php foreach($this->downloads as $idx => $filename) { ?>
|
||||||
<li>
|
<li>
|
||||||
<a href="srv/<?=hesc(urlencode($filename))?>"><?=hesc($filename)?></a>
|
<a href="srv/<?=hesc($this->downloads_hashes[$idx])?>/<?=hesc(rawurlencode($filename))?>"><?=hesc($filename)?></a>
|
||||||
<small>
|
<small>
|
||||||
<?=hesc(fbytes(filesize(BASEDIR.'wwwroot/srv/'.$filename)))?>
|
<?=hesc(fbytes(filesize(BASEDIR.'wwwroot/srv/'.$this->downloads_hashes[$idx].'/'.$filename)))?>
|
||||||
</small>
|
</small>
|
||||||
</li>
|
</li>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
@@ -243,6 +369,9 @@ class CProject {
|
|||||||
<a href="srv/<?=hesc(urlencode($this->projname))?>_<?=$idx?>.<?=str_ext($origname)?>"><img src="srv/<?=hesc(urlencode($this->projname))?>_<?=$idx?>_thumb.jpg" class="thumbimage"></a>
|
<a href="srv/<?=hesc(urlencode($this->projname))?>_<?=$idx?>.<?=str_ext($origname)?>"><img src="srv/<?=hesc(urlencode($this->projname))?>_<?=$idx?>_thumb.jpg" class="thumbimage"></a>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div style="clear:both;"></div>
|
||||||
|
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -260,14 +389,16 @@ function template($title, $content) {
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" >
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" >
|
||||||
<meta name="viewport" content="width=768px" >
|
<meta name="viewport" content="width=960" >
|
||||||
|
<link type="text/css" rel="stylesheet" href="normalize.css">
|
||||||
<link type="text/css" rel="stylesheet" href="style.css">
|
<link type="text/css" rel="stylesheet" href="style.css">
|
||||||
|
<script type="text/javascript" src="site.js"></script>
|
||||||
<title><?=hesc($title)?></title>
|
<title><?=hesc($title)?></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="container">
|
<div id="container">
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<a href="index.html"><div id="bannerlogo"></div></a>
|
<?=file_get_contents(BASEDIR.'/header.htm')?>
|
||||||
<?=$content?>
|
<?=$content?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -277,26 +408,7 @@ function template($title, $content) {
|
|||||||
return ob_get_clean();
|
return ob_get_clean();
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildall() {
|
function listprojects() {
|
||||||
|
|
||||||
// Clean up webroot
|
|
||||||
|
|
||||||
if (file_exists(BASEDIR.'wwwroot')) {
|
|
||||||
rmdir_recursive(BASEDIR.'wwwroot');
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Creating directories...\n";
|
|
||||||
|
|
||||||
mkdir(BASEDIR.'wwwroot');
|
|
||||||
mkdir(BASEDIR.'wwwroot/srv');
|
|
||||||
|
|
||||||
// Copy in static files
|
|
||||||
|
|
||||||
foreach(scandir(BASEDIR.'static') as $static) {
|
|
||||||
if ($static[0] == '.' || is_dir($static) /* fixme */) continue;
|
|
||||||
copy(BASEDIR.'static/'.$static, BASEDIR.'wwwroot/'.$static);
|
|
||||||
}
|
|
||||||
|
|
||||||
// List projects
|
// List projects
|
||||||
|
|
||||||
$ls = scandir(BASEDIR.'data');
|
$ls = scandir(BASEDIR.'data');
|
||||||
@@ -304,27 +416,49 @@ function buildall() {
|
|||||||
$projects = array();
|
$projects = array();
|
||||||
foreach($ls as $dirname) {
|
foreach($ls as $dirname) {
|
||||||
if ($dirname[0] == '.') continue;
|
if ($dirname[0] == '.') continue;
|
||||||
|
if (! is_dir(BASEDIR.'data/'.$dirname)) continue;
|
||||||
$matches = array();
|
$matches = array();
|
||||||
|
|
||||||
if (preg_match('~(?:\d+-)?(.+)~', $dirname, $matches)) {
|
if (preg_match('~(?:\d+-)?(.+)~', $dirname, $matches)) {
|
||||||
$projects[$dirname] = $matches[1];
|
$projects[$dirname] = $matches[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $projects;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildprojects($id, $projects) {
|
||||||
|
$count = 0;
|
||||||
|
|
||||||
|
foreach($projects as $dirname => $projectname) {
|
||||||
|
|
||||||
|
echo sprintf("@%1d [%3d/%3d] ".$projectname."...\n", $id, ++$count, count($projects));
|
||||||
|
|
||||||
|
$pr = new CProject($dirname, $projectname);
|
||||||
|
$pr->write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildcommon() {
|
||||||
|
|
||||||
|
echo "@0 [ 0/ ?] Common files...\n";
|
||||||
|
|
||||||
|
$projects = listprojects();
|
||||||
|
|
||||||
// Build all projects
|
// Build all projects
|
||||||
|
|
||||||
$plist = array();
|
$plist = array();
|
||||||
$count = 0;
|
|
||||||
|
|
||||||
$handles = array();
|
$handles = array();
|
||||||
$handle_lookup = array();
|
$handle_lookup = array();
|
||||||
|
|
||||||
|
$alphasort = [];
|
||||||
|
|
||||||
foreach($projects as $dirname => $projectname) {
|
foreach($projects as $dirname => $projectname) {
|
||||||
|
|
||||||
echo sprintf("[%3d/%3d] ".$projectname."...", ++$count, count($projects));
|
$pr = new CProject($dirname, $projectname);
|
||||||
|
$pr->genHomeImage(); // thumbnail
|
||||||
$pr = new CProject($dirname, $projectname);
|
|
||||||
$pr->write();
|
|
||||||
$plist[] = $pr;
|
$plist[] = $pr;
|
||||||
|
|
||||||
if (is_null($pr->homeimage)) {
|
if (is_null($pr->homeimage)) {
|
||||||
@@ -334,13 +468,25 @@ function buildall() {
|
|||||||
$handles[] = $pr->homeimage;
|
$handles[] = $pr->homeimage;
|
||||||
}
|
}
|
||||||
|
|
||||||
echo " done\n";
|
$alphasort[] = [$pr->projname, count($plist)-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usort($alphasort, function($a, $b) {
|
||||||
|
return strcasecmp($a[0], $b[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
$alphaidx = [];
|
||||||
|
|
||||||
|
foreach($alphasort as $a) {
|
||||||
|
$alphaidx[ $a[1] ] = count($alphaidx);
|
||||||
|
}
|
||||||
|
|
||||||
// Build homepage spritesheet
|
// Build homepage spritesheet
|
||||||
|
|
||||||
mkspritesheet($handles, BASEDIR.'wwwroot/logos.jpg', INDEX_THUMB_W, INDEX_THUMB_H);
|
if (count($handles)) {
|
||||||
array_map('imagedestroy', $handles); // free
|
mkspritesheet($handles, BASEDIR.'wwwroot/logos.jpg', INDEX_THUMB_W, INDEX_THUMB_H);
|
||||||
|
array_map('imagedestroy', $handles); // free
|
||||||
|
}
|
||||||
|
|
||||||
// Build index page
|
// Build index page
|
||||||
|
|
||||||
@@ -353,19 +499,32 @@ function buildall() {
|
|||||||
<!-- }} -->
|
<!-- }} -->
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
<table class="projtable">
|
<table id="projtable-main" class="projtable">
|
||||||
<?php foreach ($plist as $pr) { ?>
|
<?php foreach ($plist as $i => $pr) { ?>
|
||||||
<tr>
|
<tr class="<?=$pr->getClassAttr()?>"
|
||||||
|
data-sort-mt="-<?=$pr->lastupdate?>"
|
||||||
|
data-sort-ct="<?=$i?>"
|
||||||
|
data-sort-al="<?=$alphaidx[$i]?>"
|
||||||
|
>
|
||||||
<td>
|
<td>
|
||||||
<a href="<?=hesc(urlencode($pr->projname))?>.html"><?=(is_null($handle_lookup[$pr->projname]) ? '<div class="no-image"></div>' : '<div class="homeimage homeimage-sprite" style="background-position:0 -'.($handle_lookup[$pr->projname]*INDEX_THUMB_H).'px"></div>')?></a>
|
<a href="<?=hesc(urlencode($pr->projname))?>.html"><?=(is_null($handle_lookup[$pr->projname]) ? '<div class="no-image"></div>' : '<div class="homeimage homeimage-sprite" style="background-position:0 -'.($handle_lookup[$pr->projname]*INDEX_THUMB_H).'px"></div>')?></a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<strong><?=hesc($pr->projname)?></strong>,
|
<strong><?=hesc(str_replace('_', ' ', $pr->projname))?></strong><?php if (SHOW_BLURBS) { ?>,
|
||||||
<?=hesc($pr->shortdesc)?>
|
<?=hesc($pr->shortdesc)?>
|
||||||
<a href="<?=hesc(urlencode($pr->projname))?>.html">more...</a>
|
<?php } ?>
|
||||||
<?php if (strlen($pr->subtag)) { ?>
|
<a href="<?=hesc(urlencode($pr->projname))?>.html" class="article-read-more">more...</a>
|
||||||
|
<?php if (strlen($pr->subtag) || count($pr->tags)) { ?>
|
||||||
<br>
|
<br>
|
||||||
<small><?=hesc($pr->subtag)?></small>
|
<small>
|
||||||
|
<?=hesc($pr->subtag)?>
|
||||||
|
<?php if (strlen($pr->subtag) && count($pr->tags)) { ?>
|
||||||
|
::
|
||||||
|
<?php } ?>
|
||||||
|
<?php foreach($pr->tags as $tag) { ?>
|
||||||
|
<a class="tag tag-link" data-tag="<?=hesc($tag)?>"><?=hesc($tag)?></a>
|
||||||
|
<?php } ?>
|
||||||
|
</small>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -375,9 +534,66 @@ function buildall() {
|
|||||||
|
|
||||||
$index = template(SITE_TITLE, ob_get_clean());
|
$index = template(SITE_TITLE, ob_get_clean());
|
||||||
file_put_contents(BASEDIR.'wwwroot/index.html', $index);
|
file_put_contents(BASEDIR.'wwwroot/index.html', $index);
|
||||||
|
|
||||||
echo "All processes complete.\n";
|
// Done
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildall();
|
function buildredirects($redirects) {
|
||||||
|
foreach($redirects as $oldname => $newname) {
|
||||||
|
ob_start();
|
||||||
|
?>
|
||||||
|
<meta http-equiv="refresh" content="0; url=<?=hesc($newname)?>.html">
|
||||||
|
<a href="<?=hesc($newname)?>.html">Moved »</a>
|
||||||
|
<?php
|
||||||
|
$page = ob_get_clean();
|
||||||
|
file_put_contents(BASEDIR.'wwwroot/'.$oldname.'.html', $page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function main($args) {
|
||||||
|
$basedir = './';
|
||||||
|
$total = $args[0];
|
||||||
|
$pos = $args[1];
|
||||||
|
|
||||||
|
// Parse configuration
|
||||||
|
|
||||||
|
$config = @parse_ini_file(
|
||||||
|
$basedir . 'config.ini',
|
||||||
|
true,
|
||||||
|
INI_SCANNER_RAW
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($config === false) {
|
||||||
|
die("[FATAL] Couldn't load '${basedir}/config.ini'!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
define('BASEDIR', $basedir);
|
||||||
|
define('SITE_TITLE', trim($config['codesite']['title']));
|
||||||
|
define('PAGE_THUMB_W', intval($config['codesite']['page_thumb_w']));
|
||||||
|
define('PAGE_THUMB_H', intval($config['codesite']['page_thumb_h']));
|
||||||
|
define('INDEX_THUMB_W', intval($config['codesite']['index_thumb_w']));
|
||||||
|
define('INDEX_THUMB_H', intval($config['codesite']['index_thumb_h']));
|
||||||
|
define('SHOW_BLURBS', !(isset($config['codesite']['blurbs']) && $config['codesite']['blurbs'] === 'off') );
|
||||||
|
define('ARTICLE_HEADER', (isset($config['codesite']['article_header']) ? $config['codesite']['article_header'] : 'ABOUT') );
|
||||||
|
define('SHIELDS_PREFIX', isset($config['codesite']['shields_prefix']));
|
||||||
|
|
||||||
|
// Perform build tasks
|
||||||
|
|
||||||
|
if ($pos == 0) {
|
||||||
|
buildcommon();
|
||||||
|
if (array_key_exists('redirect', $config)) {
|
||||||
|
buildredirects( $config['redirect'] );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buildprojects($pos, array_decimate(listprojects(), $total, $pos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entry point
|
||||||
|
//
|
||||||
|
|
||||||
|
ini_set('display_errors', 'On');
|
||||||
|
date_default_timezone_set('Etc/UTC');
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
|
main(array_slice($_SERVER['argv'], 1));
|
||||||
|
|||||||
60
rebuild.sh
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
THREADS=4
|
||||||
|
|
||||||
|
buildsite() {
|
||||||
|
|
||||||
|
local basedir="$(realpath .)"
|
||||||
|
local rebuild="${basedir}/rebuild.php"
|
||||||
|
|
||||||
|
if [[ "$(uname -o)" == "Cygwin" ]] ; then
|
||||||
|
rebuild="$(cygpath -w "$rebuild")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Site: ${1}"
|
||||||
|
|
||||||
|
pushd "$1" >/dev/null
|
||||||
|
|
||||||
|
echo "Cleaning target directory..."
|
||||||
|
|
||||||
|
if [[ -d wwwroot ]] ; then
|
||||||
|
rm -r wwwroot
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p wwwroot/srv
|
||||||
|
|
||||||
|
if [[ ! -d static ]] ; then
|
||||||
|
mkdir static
|
||||||
|
fi
|
||||||
|
cp "${basedir}/static_global/"* wwwroot || true
|
||||||
|
cp static/* wwwroot || true
|
||||||
|
|
||||||
|
for htm in footer header homepage_blurb ; do
|
||||||
|
if [[ ! -f "${htm}.htm" ]] ; then
|
||||||
|
touch "${htm}.htm"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Building pages..."
|
||||||
|
|
||||||
|
for i in $(seq 0 "$THREADS") ; do
|
||||||
|
php "$rebuild" "$THREADS" "$i" &
|
||||||
|
done
|
||||||
|
wait
|
||||||
|
|
||||||
|
echo "Site: ${1} finished."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
for site in sites/* ; do
|
||||||
|
buildsite "$site"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
|
|
||||||
|
read -p "Press any key to continue..."
|
||||||
14
sites/code.ivysaur.me/config.ini
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[codesite]
|
||||||
|
title=code.ivysaur.me
|
||||||
|
page_thumb_w=60
|
||||||
|
page_thumb_h=60
|
||||||
|
index_thumb_w=90
|
||||||
|
index_thumb_h=32
|
||||||
|
|
||||||
|
shields_prefix=true
|
||||||
|
|
||||||
|
; n.b. Recommend a multiple of the JPEG iDCT block size for index_thumb_h
|
||||||
|
|
||||||
|
[redirect]
|
||||||
|
; old project name = new project name
|
||||||
|
code.ivysaur.me=codesite
|
||||||
11
sites/code.ivysaur.me/footer.htm
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<p>
|
||||||
|
<strong>CONTACT</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
For bug reports, feature requests, or if you need any help, please
|
||||||
|
<a
|
||||||
|
href="http://www.google.com/recaptcha/mailhide/d?k=01GuAWzMc9JjSdooo-2KCMQA==&c=kgR3dBrP39yhPIy8FvLFbuBLmWqorQBDc_Zjbw6NAmU="
|
||||||
|
onclick="window.open('http://www.google.com/recaptcha/mailhide/d?k\07501GuAWzMc9JjSdooo-2KCMQA\75\75\46c\75kgR3dBrP39yhPIy8FvLFbuBLmWqorQBDc_Zjbw6NAmU\075', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;"
|
||||||
|
title="Reveal this e-mail address"
|
||||||
|
>click here</a> to email me.
|
||||||
|
</p>
|
||||||
1
sites/code.ivysaur.me/header.htm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<h1><a href="index.html"><div id="ivylogo"></div>code.ivysaur.me</a></h1>
|
||||||
@@ -16,14 +16,11 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
For bug reports, feature requests, or if you need any help, please
|
<select id="sortorder" style="float:right;">
|
||||||
<a
|
<option value="a">Youngest project first</option>
|
||||||
href="http://www.google.com/recaptcha/mailhide/d?k=01GuAWzMc9JjSdooo-2KCMQA==&c=kgR3dBrP39yhPIy8FvLFbuBLmWqorQBDc_Zjbw6NAmU="
|
<option value="b">Recent updates first</option>
|
||||||
onclick="window.open('http://www.google.com/recaptcha/mailhide/d?k\07501GuAWzMc9JjSdooo-2KCMQA\75\75\46c\75kgR3dBrP39yhPIy8FvLFbuBLmWqorQBDc_Zjbw6NAmU\075', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;"
|
<option value="c">Alphabetical</option>
|
||||||
title="Reveal this e-mail address"
|
</select>
|
||||||
>click here</a> to email me.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<strong>PROJECTS</strong>
|
<strong>PROJECTS</strong>
|
||||||
</p>
|
</p>
|
||||||
BIN
sites/code.ivysaur.me/static/favicon.ico
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
sites/code.ivysaur.me/static/greyzz.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
sites/code.ivysaur.me/static/greyzz_@2X.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
sites/code.ivysaur.me/static/ivysaur24.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
198
sites/code.ivysaur.me/static/style.css
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
/* style.css */
|
||||||
|
|
||||||
|
html {
|
||||||
|
overflow-y:scroll; /* always display scrollbar to prevent horizontal lurch */
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
border:0;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color:#4078c0;
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
cursor:pointer;
|
||||||
|
text-decoration:underline;
|
||||||
|
}
|
||||||
|
h1 a {
|
||||||
|
color:black;
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
h1 a:hover {
|
||||||
|
color:black;
|
||||||
|
}
|
||||||
|
h1,h2,h3 {
|
||||||
|
margin-top:0;
|
||||||
|
}
|
||||||
|
.code {
|
||||||
|
background: #F8F8F8;
|
||||||
|
font-family:Consolas,monospace;
|
||||||
|
white-space:pre;
|
||||||
|
}
|
||||||
|
.code-multiline {
|
||||||
|
display:inline-block;
|
||||||
|
padding:8px;
|
||||||
|
border-radius:8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
/* structural */
|
||||||
|
height:100%;
|
||||||
|
min-height:100%;
|
||||||
|
margin:0;
|
||||||
|
border:0;
|
||||||
|
padding:0;
|
||||||
|
|
||||||
|
/* cosmetic */
|
||||||
|
font-family:"Helvetica Neue","Segoe UI",Arial,sans-serif;
|
||||||
|
font-size:13px;
|
||||||
|
line-height:1.4;
|
||||||
|
background:#DDD url('greyzz.png'); /* thanks subtlepatterns.com ! */
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
margin:0 auto;
|
||||||
|
width:960px;
|
||||||
|
position:relative;
|
||||||
|
|
||||||
|
height:auto !important;
|
||||||
|
height:100%; /* oldIE */
|
||||||
|
min-height:100%;
|
||||||
|
|
||||||
|
/* cosmetic */
|
||||||
|
background:white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
padding:14px;
|
||||||
|
background:white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
.tag::before {
|
||||||
|
content:"";
|
||||||
|
|
||||||
|
display:inline-block;
|
||||||
|
width:7px;
|
||||||
|
height:7px;
|
||||||
|
|
||||||
|
margin-right:2px;
|
||||||
|
|
||||||
|
background:transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAZUlEQVQI12P4//8/Awyrqqp6KSkp/QdhFRWV7cgS+kDBN0B8RVlZuRikACahB+T8ger6BMTXwJJAiTwg4xvMOCj+ART3ZwCa3YYm8QcopgsyEWasDVT3W5AVMHcgO6gViNORXQ8A84NToxbSsJcAAAAASUVORK5CYII=') no-repeat 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-filter-warn {
|
||||||
|
position:fixed;
|
||||||
|
top:0;
|
||||||
|
right:0;
|
||||||
|
|
||||||
|
padding:4px;
|
||||||
|
|
||||||
|
background:lightyellow;
|
||||||
|
border-bottom: 1px solid #888;
|
||||||
|
border-left:1px solid #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
.projtable {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.projtable tr {
|
||||||
|
transition:0.2s linear;
|
||||||
|
}
|
||||||
|
.projtable tr:hover {
|
||||||
|
background:#F8F8F8;
|
||||||
|
}
|
||||||
|
.projtable td {
|
||||||
|
padding: 2px 4px;
|
||||||
|
}
|
||||||
|
.projtable small {
|
||||||
|
color:grey;
|
||||||
|
font-style:italic;
|
||||||
|
}
|
||||||
|
.projtable tr td:first-child {
|
||||||
|
width:95px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projinfo {
|
||||||
|
}
|
||||||
|
.projbody {
|
||||||
|
}
|
||||||
|
.projbody_halfw {
|
||||||
|
float:left;
|
||||||
|
width: 860px; /* 740px full - 60px rhs column - 2px border */
|
||||||
|
}
|
||||||
|
.projbody_fullw {
|
||||||
|
|
||||||
|
}
|
||||||
|
.projimg {
|
||||||
|
float:right;
|
||||||
|
width:62px; /* 60px + 2px border */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
@media screen and (max-width:960px) {
|
||||||
|
|
||||||
|
#container {
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.projimg {
|
||||||
|
float:clear;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.projbody_halfw {
|
||||||
|
float:clear;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
#ivylogo {
|
||||||
|
background:transparent url('ivysaur24.png') no-repeat 0 0;
|
||||||
|
width:24px;
|
||||||
|
height:24px;
|
||||||
|
display:inline-block;
|
||||||
|
*display:block;
|
||||||
|
*zoom:1;
|
||||||
|
margin-right:4px;
|
||||||
|
position:relative;
|
||||||
|
top:4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
.homeimage {
|
||||||
|
width:90px;
|
||||||
|
height:32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.homeimage-sprite {
|
||||||
|
background: white url('logos.jpg') no-repeat 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbimage {
|
||||||
|
width:60px;
|
||||||
|
height:60px;
|
||||||
|
opacity: 0.8;
|
||||||
|
transition:0.2s opacity;
|
||||||
|
border:1px solid lightgrey;
|
||||||
|
}
|
||||||
|
.thumbimage:hover {
|
||||||
|
opacity:1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-image {
|
||||||
|
width:90px;
|
||||||
|
height:32px;
|
||||||
|
display:block;
|
||||||
|
background: white url('no_image.png') no-repeat 0 0;
|
||||||
|
}
|
||||||
13
sites/codesite.example.com/config.ini
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[codesite]
|
||||||
|
title=codesite.example.com
|
||||||
|
page_thumb_w=60
|
||||||
|
page_thumb_h=60
|
||||||
|
index_thumb_w=90
|
||||||
|
index_thumb_h=32
|
||||||
|
|
||||||
|
; n.b. Recommend a multiple of the JPEG iDCT block size for index_thumb_h
|
||||||
|
|
||||||
|
[redirect]
|
||||||
|
; old project name = new project name
|
||||||
|
old-project-name=example-project
|
||||||
|
|
||||||
6
sites/codesite.example.com/footer.htm
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<p>
|
||||||
|
<strong>FOOTER</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Content here.
|
||||||
|
</p>
|
||||||
1
sites/codesite.example.com/header.htm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<h1>HEADER</h1>
|
||||||
14
sites/codesite.example.com/homepage_blurb.htm
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
<p>
|
||||||
|
Homepage blurb goes here.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<select id="sortorder" style="float:right;">
|
||||||
|
<option value="a">Youngest project first</option>
|
||||||
|
<option value="b">Recent updates first</option>
|
||||||
|
<option value="c">Alphabetical</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<strong>PROJECTS</strong>
|
||||||
|
</p>
|
||||||
|
Before Width: | Height: | Size: 233 B After Width: | Height: | Size: 233 B |
|
Before Width: | Height: | Size: 264 B After Width: | Height: | Size: 264 B |
@@ -1,13 +1,24 @@
|
|||||||
/* style.css */
|
/* style.css */
|
||||||
|
|
||||||
|
html {
|
||||||
|
overflow-y:scroll; /* always display scrollbar to prevent horizontal lurch */
|
||||||
|
}
|
||||||
img {
|
img {
|
||||||
border:0;
|
border:0;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color:black;
|
color:black;
|
||||||
|
text-decoration:underline;
|
||||||
}
|
}
|
||||||
a:hover {
|
a:hover {
|
||||||
color:blue;
|
color:blue;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
h1 a {
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
h1 a:hover {
|
||||||
|
color:black;
|
||||||
}
|
}
|
||||||
h1,h2,h3 {
|
h1,h2,h3 {
|
||||||
margin-top:0;
|
margin-top:0;
|
||||||
@@ -27,6 +38,8 @@ html, body {
|
|||||||
padding:0;
|
padding:0;
|
||||||
|
|
||||||
/* cosmetic */
|
/* cosmetic */
|
||||||
|
font-family:"Helvetica Neue","Segoe UI",Arial,sans-serif;
|
||||||
|
font-size:12px;
|
||||||
background:#DDD url('pixel_weave.png'); /* thanks subtlepatterns.com ! */
|
background:#DDD url('pixel_weave.png'); /* thanks subtlepatterns.com ! */
|
||||||
color:#333;
|
color:#333;
|
||||||
}
|
}
|
||||||
@@ -51,6 +64,32 @@ html, body {
|
|||||||
|
|
||||||
/* */
|
/* */
|
||||||
|
|
||||||
|
.tag::before {
|
||||||
|
content:"";
|
||||||
|
|
||||||
|
display:inline-block;
|
||||||
|
width:7px;
|
||||||
|
height:7px;
|
||||||
|
|
||||||
|
margin-right:2px;
|
||||||
|
|
||||||
|
background:transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAZUlEQVQI12P4//8/Awyrqqp6KSkp/QdhFRWV7cgS+kDBN0B8RVlZuRikACahB+T8ger6BMTXwJJAiTwg4xvMOCj+ART3ZwCa3YYm8QcopgsyEWasDVT3W5AVMHcgO6gViNORXQ8A84NToxbSsJcAAAAASUVORK5CYII=') no-repeat 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-filter-warn {
|
||||||
|
position:fixed;
|
||||||
|
top:0;
|
||||||
|
right:0;
|
||||||
|
|
||||||
|
padding:4px;
|
||||||
|
|
||||||
|
background:lightyellow;
|
||||||
|
border-bottom: 1px solid #888;
|
||||||
|
border-left:1px solid #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
.projtable {
|
.projtable {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width:100%;
|
width:100%;
|
||||||
@@ -68,6 +107,9 @@ html, body {
|
|||||||
color:grey;
|
color:grey;
|
||||||
font-style:italic;
|
font-style:italic;
|
||||||
}
|
}
|
||||||
|
.projtable tr td:first-child {
|
||||||
|
width:95px;
|
||||||
|
}
|
||||||
|
|
||||||
.projinfo {
|
.projinfo {
|
||||||
position:relative;
|
position:relative;
|
||||||
@@ -91,19 +133,6 @@ html, body {
|
|||||||
|
|
||||||
/* */
|
/* */
|
||||||
|
|
||||||
#bannerlogo {
|
|
||||||
width:631px;
|
|
||||||
height:35px;
|
|
||||||
margin:0 auto;
|
|
||||||
background: white url('header.png') no-repeat 0 0;
|
|
||||||
padding:8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headimg {
|
|
||||||
width:310px;
|
|
||||||
height:62px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.homeimage {
|
.homeimage {
|
||||||
width:90px;
|
width:90px;
|
||||||
height:32px;
|
height:32px;
|
||||||
11
sites/storytime.ivysaur.me/config.ini
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[codesite]
|
||||||
|
title=storytime.ivysaur.me
|
||||||
|
page_thumb_w=60
|
||||||
|
page_thumb_h=60
|
||||||
|
index_thumb_w=90
|
||||||
|
index_thumb_h=32
|
||||||
|
|
||||||
|
blurbs=off
|
||||||
|
article_header=ARTICLE
|
||||||
|
|
||||||
|
; n.b. Recommend a multiple of the JPEG iDCT block size for index_thumb_h
|
||||||
10
sites/storytime.ivysaur.me/footer.htm
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<p>
|
||||||
|
<strong>CONTACT</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a
|
||||||
|
href="http://www.google.com/recaptcha/mailhide/d?k=01GuAWzMc9JjSdooo-2KCMQA==&c=kgR3dBrP39yhPIy8FvLFbuBLmWqorQBDc_Zjbw6NAmU="
|
||||||
|
onclick="window.open('http://www.google.com/recaptcha/mailhide/d?k\07501GuAWzMc9JjSdooo-2KCMQA\75\75\46c\75kgR3dBrP39yhPIy8FvLFbuBLmWqorQBDc_Zjbw6NAmU\075', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;"
|
||||||
|
title="Reveal this e-mail address"
|
||||||
|
>Click here</a> to email me.
|
||||||
|
</p>
|
||||||
1
sites/storytime.ivysaur.me/header.htm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<h1><a href="index.html"><div id="ivylogo"></div>storytime.ivysaur.me</a></h1>
|
||||||
12
sites/storytime.ivysaur.me/homepage_blurb.htm
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<p>
|
||||||
|
The stories and information posted here are artistic works of fiction and falsehood. Only a fool would take anything posted here as fact.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>LICENSE</strong>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Please consider all articles on this page to be under the <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">CC-BY-SA 4.0 International license</a> unless otherwise specified.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>ARTICLES</strong>
|
||||||
|
</p>
|
||||||
BIN
sites/storytime.ivysaur.me/static/11.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
sites/storytime.ivysaur.me/static/favicon.ico
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
sites/storytime.ivysaur.me/static/ivysaur24.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
sites/storytime.ivysaur.me/static/no_image.png
Normal file
|
After Width: | Height: | Size: 416 B |
BIN
sites/storytime.ivysaur.me/static/pixel_weave.png
Normal file
|
After Width: | Height: | Size: 233 B |
BIN
sites/storytime.ivysaur.me/static/pixel_weave_@2X.png
Normal file
|
After Width: | Height: | Size: 264 B |
187
sites/storytime.ivysaur.me/static/style.css
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
/* style.css */
|
||||||
|
|
||||||
|
html {
|
||||||
|
overflow-y:scroll; /* always display scrollbar to prevent horizontal lurch */
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
border:0;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color:black;
|
||||||
|
text-decoration:underline;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color:blue;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
h1 a {
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
h1 a:hover {
|
||||||
|
color:black;
|
||||||
|
}
|
||||||
|
h1,h2,h3 {
|
||||||
|
margin-top:0;
|
||||||
|
}
|
||||||
|
.code {
|
||||||
|
background: #F8F8F8;
|
||||||
|
font-family:Consolas,monospace;
|
||||||
|
white-space:pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
/* structural */
|
||||||
|
height:100%;
|
||||||
|
min-height:100%;
|
||||||
|
margin:0;
|
||||||
|
border:0;
|
||||||
|
padding:0;
|
||||||
|
|
||||||
|
/* cosmetic */
|
||||||
|
font-family:"Helvetica Neue","Segoe UI",Arial,sans-serif;
|
||||||
|
font-size:12px;
|
||||||
|
background:#DDD url('pixel_weave.png'); /* thanks subtlepatterns.com ! */
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
margin:0 auto;
|
||||||
|
width:768px;
|
||||||
|
position:relative;
|
||||||
|
|
||||||
|
height:auto !important;
|
||||||
|
height:100%; /* oldIE */
|
||||||
|
min-height:100%;
|
||||||
|
|
||||||
|
/* cosmetic */
|
||||||
|
background:white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
padding:14px;
|
||||||
|
background:white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
.tag::before {
|
||||||
|
content:"";
|
||||||
|
|
||||||
|
display:inline-block;
|
||||||
|
width:7px;
|
||||||
|
height:7px;
|
||||||
|
|
||||||
|
margin-right:2px;
|
||||||
|
|
||||||
|
background:transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAZUlEQVQI12P4//8/Awyrqqp6KSkp/QdhFRWV7cgS+kDBN0B8RVlZuRikACahB+T8ger6BMTXwJJAiTwg4xvMOCj+ART3ZwCa3YYm8QcopgsyEWasDVT3W5AVMHcgO6gViNORXQ8A84NToxbSsJcAAAAASUVORK5CYII=') no-repeat 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-filter-warn {
|
||||||
|
position:fixed;
|
||||||
|
top:0;
|
||||||
|
right:0;
|
||||||
|
|
||||||
|
padding:4px;
|
||||||
|
|
||||||
|
background:lightyellow;
|
||||||
|
border-bottom: 1px solid #888;
|
||||||
|
border-left:1px solid #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
.projtable {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.projtable tr {
|
||||||
|
transition:0.2s linear;
|
||||||
|
}
|
||||||
|
.projtable tr:hover {
|
||||||
|
background:#F8F8F8;
|
||||||
|
}
|
||||||
|
.projtable td {
|
||||||
|
padding: 2px 4px;
|
||||||
|
}
|
||||||
|
.projtable small {
|
||||||
|
color:grey;
|
||||||
|
font-style:italic;
|
||||||
|
}
|
||||||
|
.projtable tr td:first-child {
|
||||||
|
width:95px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.projinfo {
|
||||||
|
}
|
||||||
|
.projbody {
|
||||||
|
}
|
||||||
|
.projbody_halfw {
|
||||||
|
float:left;
|
||||||
|
width: 678px; /* 740px full - 60px rhs column - 2px border */
|
||||||
|
}
|
||||||
|
.projbody_fullw {
|
||||||
|
|
||||||
|
}
|
||||||
|
.projimg {
|
||||||
|
float:right;
|
||||||
|
width:62px; /* 60px + 2px border */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
#ivylogo {
|
||||||
|
background:transparent url('ivysaur24.png') no-repeat 0 0;
|
||||||
|
width:24px;
|
||||||
|
height:24px;
|
||||||
|
display:inline-block;
|
||||||
|
*display:block;
|
||||||
|
*zoom:1;
|
||||||
|
margin-right:4px;
|
||||||
|
position:relative;
|
||||||
|
top:4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
.homeimage {
|
||||||
|
width:90px;
|
||||||
|
height:32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.homeimage-sprite {
|
||||||
|
background: white url('logos.jpg') no-repeat 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbimage {
|
||||||
|
width:60px;
|
||||||
|
height:60px;
|
||||||
|
opacity: 0.8;
|
||||||
|
transition:0.2s opacity;
|
||||||
|
border:1px solid lightgrey;
|
||||||
|
}
|
||||||
|
.thumbimage:hover {
|
||||||
|
opacity:1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-image {
|
||||||
|
width:90px;
|
||||||
|
height:32px;
|
||||||
|
display:block;
|
||||||
|
background: white url('no_image.png') no-repeat 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
.spoiler {
|
||||||
|
color:black;
|
||||||
|
background:black;
|
||||||
|
}
|
||||||
|
.spoiler:hover {
|
||||||
|
color:white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-read-more {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 436 B After Width: | Height: | Size: 436 B |
406
static_global/normalize.css
vendored
Normal file
@@ -0,0 +1,406 @@
|
|||||||
|
/*! normalize.css v2.1.3 | MIT License | git.io/normalize */
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
HTML5 display definitions
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct `block` display not defined in IE 8/9.
|
||||||
|
*/
|
||||||
|
|
||||||
|
article,
|
||||||
|
aside,
|
||||||
|
details,
|
||||||
|
figcaption,
|
||||||
|
figure,
|
||||||
|
footer,
|
||||||
|
header,
|
||||||
|
hgroup,
|
||||||
|
main,
|
||||||
|
nav,
|
||||||
|
section,
|
||||||
|
summary {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct `inline-block` display not defined in IE 8/9.
|
||||||
|
*/
|
||||||
|
|
||||||
|
audio,
|
||||||
|
canvas,
|
||||||
|
video {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent modern browsers from displaying `audio` without controls.
|
||||||
|
* Remove excess height in iOS 5 devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
audio:not([controls]) {
|
||||||
|
display: none;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address `[hidden]` styling not present in IE 8/9.
|
||||||
|
* Hide the `template` element in IE, Safari, and Firefox < 22.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[hidden],
|
||||||
|
template {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Base
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Set default font family to sans-serif.
|
||||||
|
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||||
|
* user zoom.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: sans-serif; /* 1 */
|
||||||
|
-ms-text-size-adjust: 100%; /* 2 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove default margin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Links
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the gray background color from active links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address `outline` inconsistency between Chrome and other browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a:focus {
|
||||||
|
outline: thin dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Improve readability when focused and also mouse hovered in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a:active,
|
||||||
|
a:hover {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Typography
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address variable `h1` font-size and margin within `section` and `article`
|
||||||
|
* contexts in Firefox 4+, Safari 5, and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin: 0.67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address styling not present in IE 8/9, Safari 5, and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abbr[title] {
|
||||||
|
border-bottom: 1px dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address styling not present in Safari 5 and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
dfn {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address differences between Firefox and other browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hr {
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address styling not present in IE 8/9.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mark {
|
||||||
|
background: #ff0;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct font family set oddly in Safari 5 and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
pre,
|
||||||
|
samp {
|
||||||
|
font-family: monospace, serif;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Improve readability of pre-formatted text in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set consistent quote types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
q {
|
||||||
|
quotes: "\201C" "\201D" "\2018" "\2019";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address inconsistent and variable font size in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Embedded content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove border when inside `a` element in IE 8/9.
|
||||||
|
*/
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct overflow displayed oddly in IE 9.
|
||||||
|
*/
|
||||||
|
|
||||||
|
svg:not(:root) {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Figures
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address margin not present in IE 8/9 and Safari 5.
|
||||||
|
*/
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Forms
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define consistent border, margin, and padding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
border: 1px solid #c0c0c0;
|
||||||
|
margin: 0 2px;
|
||||||
|
padding: 0.35em 0.625em 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct `color` not being inherited in IE 8/9.
|
||||||
|
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||||
|
*/
|
||||||
|
|
||||||
|
legend {
|
||||||
|
border: 0; /* 1 */
|
||||||
|
padding: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct font family not being inherited in all browsers.
|
||||||
|
* 2. Correct font size not being inherited in all browsers.
|
||||||
|
* 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-family: inherit; /* 1 */
|
||||||
|
font-size: 100%; /* 2 */
|
||||||
|
margin: 0; /* 3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||||
|
* the UA stylesheet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input {
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||||
|
* All other form control elements do not inherit `text-transform` values.
|
||||||
|
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
|
||||||
|
* Correct `select` style inheritance in Firefox 4+ and Opera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
select {
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||||
|
* and `video` controls.
|
||||||
|
* 2. Correct inability to style clickable `input` types in iOS.
|
||||||
|
* 3. Improve usability and consistency of cursor style between image-type
|
||||||
|
* `input` and others.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
html input[type="button"], /* 1 */
|
||||||
|
input[type="reset"],
|
||||||
|
input[type="submit"] {
|
||||||
|
-webkit-appearance: button; /* 2 */
|
||||||
|
cursor: pointer; /* 3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-set default cursor for disabled elements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button[disabled],
|
||||||
|
html input[disabled] {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
||||||
|
* 2. Remove excess padding in IE 8/9/10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
padding: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
|
||||||
|
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
|
||||||
|
* (include `-moz` to future-proof).
|
||||||
|
*/
|
||||||
|
|
||||||
|
input[type="search"] {
|
||||||
|
-webkit-appearance: textfield; /* 1 */
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
-webkit-box-sizing: content-box; /* 2 */
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove inner padding and search cancel button in Safari 5 and Chrome
|
||||||
|
* on OS X.
|
||||||
|
*/
|
||||||
|
|
||||||
|
input[type="search"]::-webkit-search-cancel-button,
|
||||||
|
input[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove inner padding and border in Firefox 4+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
input::-moz-focus-inner {
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Remove default vertical scrollbar in IE 8/9.
|
||||||
|
* 2. Improve readability and alignment in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto; /* 1 */
|
||||||
|
vertical-align: top; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Tables
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove most spacing between table cells.
|
||||||
|
*/
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
97
static_global/site.js
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var show_all = function() {
|
||||||
|
var tr = document.querySelectorAll(".projtable tr");
|
||||||
|
for (var i = 0, e = tr.length; i !== e; ++i) {
|
||||||
|
tr[i].style.display = "table-row";
|
||||||
|
}
|
||||||
|
|
||||||
|
var warn = document.querySelector(".tag-filter-warn");
|
||||||
|
warn.parentNode.removeChild(warn);
|
||||||
|
};
|
||||||
|
|
||||||
|
var show_tag = function(tag) {
|
||||||
|
if (document.querySelector(".tag-filter-warn") !== null) {
|
||||||
|
show_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
var tr = document.querySelectorAll(".projtable tr");
|
||||||
|
for (var i = 0, e = tr.length; i !== e; ++i) {
|
||||||
|
tr[i].style.display = (tr[i].className.split(" ").indexOf("taggedWith-"+tag) === -1) ? "none" : "table-row";
|
||||||
|
}
|
||||||
|
|
||||||
|
var div = document.createElement("div");
|
||||||
|
div.className = "tag-filter-warn";
|
||||||
|
div.innerHTML = "Filtering by tag. <a>reset</a>";
|
||||||
|
document.body.appendChild(div);
|
||||||
|
|
||||||
|
document.querySelector(".tag-filter-warn a").addEventListener('click', function() {
|
||||||
|
show_all();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var get_show_tag = function(tag) {
|
||||||
|
return function() {
|
||||||
|
show_tag(tag);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var sort_rows = function(cb) {
|
||||||
|
var tr = document.querySelectorAll(".projtable tr");
|
||||||
|
var items = [];
|
||||||
|
for (var i = 0, e = tr.length; i !== e; ++i) {
|
||||||
|
items.push([i, cb(tr[i])]);
|
||||||
|
}
|
||||||
|
items.sort(function(a, b) {
|
||||||
|
return (a[1] - b[1]);
|
||||||
|
});
|
||||||
|
for (var i = 0, e = items.length; i !== e; ++i) {
|
||||||
|
var el = tr[items[i][0]];
|
||||||
|
var parent = el.parentElement;
|
||||||
|
parent.removeChild(el);
|
||||||
|
parent.appendChild(el);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var sort_update = function() {
|
||||||
|
var cb;
|
||||||
|
switch(document.getElementById('sortorder').value) {
|
||||||
|
case 'a':
|
||||||
|
default: {
|
||||||
|
cb = function(el) {
|
||||||
|
return el.getAttribute('data-sort-ct');
|
||||||
|
};
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 'b': {
|
||||||
|
cb = function(el) {
|
||||||
|
return el.getAttribute('data-sort-mt');
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 'c': {
|
||||||
|
cb = function(el) {
|
||||||
|
return el.getAttribute('data-sort-al');
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
};
|
||||||
|
sort_rows(cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
var taglinks = document.querySelectorAll(".tag-link");
|
||||||
|
for (var i = 0, e = taglinks.length; i !== e; ++i) {
|
||||||
|
var tag = taglinks[i].getAttribute("data-tag");
|
||||||
|
taglinks[i].addEventListener('click', get_show_tag(tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
var so = document.getElementById('sortorder');
|
||||||
|
if (so) {
|
||||||
|
so.addEventListener('change', sort_update);
|
||||||
|
sort_update();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||