5 Commits
v64 ... v39

Author SHA1 Message Date
f08081a129 remove some more ivysaur.me references 2
--HG--
branch : sanitise-paths
2014-07-03 22:01:04 +12:00
8c4754ae8d remove some more ivysaur.me references
--HG--
branch : sanitise-paths
2014-07-03 21:59:42 +12:00
fccaa6a326 Merge with default
--HG--
branch : sanitise-paths
2014-07-03 21:58:05 +12:00
3073231d38 remove homepage blurb for publication
--HG--
branch : sanitise-paths
2013-09-28 13:35:43 +12:00
0d522e1cd1 remove all branding for publication
--HG--
branch : sanitise-paths
2013-09-28 13:33:47 +12:00
31 changed files with 55 additions and 518 deletions

View File

@@ -1,4 +1,3 @@
mode:regex
^_dist/
^sites/[^/]+/data/
^sites/[^/]+/wwwroot/
wwwroot/*
nbproject/*
data/*

View File

@@ -1 +0,0 @@
42a17645b5b21d7fe395767de7fa3e26ee999014 release-r54

View File

@@ -1,16 +0,0 @@
- Support project redirection (e.g. `code.ivysaur.me` was renamed to `codesite`, breaking links)
- If no projects have any images, don't generate spritesheet
- Move tag javascript and no-image image out of per-site configuration
- Merge "written in" and "tags"
- Per-project directories, to prevent overwriting files (e.g. 'screenshot.jpg')
- Cache recent changes somehow
- RSS for recent changes
- RSS for all projects

View File

@@ -1,40 +0,0 @@
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: 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

3
deploy.cmd Normal file
View File

@@ -0,0 +1,3 @@
@echo off
start C:\path\to\cygwin\bin\mintty.exe /bin/bash -l -c "rsync -avz -e ""ssh -i /cygdrive/c/path/to/deploy_key"" --progress /cygdrive/c/path/to/code/wwwroot www-data@your-web-server:/var/www/path/to/code-site/"

View File

@@ -1,16 +0,0 @@
#!/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..."

8
homepage_blurb.htm Normal file
View File

@@ -0,0 +1,8 @@
<p>
Homepage blurb goes here.
</p>
<p>
<strong>PROJECTS</strong>
</p>

View File

@@ -1,9 +0,0 @@
#!/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..."

3
rebuild.cmd Normal file
View File

@@ -0,0 +1,3 @@
@echo off
C:\path\to\php_54\php.exe rebuild.php
pause

View File

@@ -3,6 +3,16 @@
// Code-hosting website
// ````````````````````
// CONFIGURATION
// `````````````
define('BASEDIR', __DIR__.'\\');
define('SITE_TITLE', 'codesite');
define('PAGE_THUMB_W', 60);
define('PAGE_THUMB_H', 60);
define('INDEX_THUMB_W', 90);
define('INDEX_THUMB_H', 32); // recommend a multiple of the jpg iDCT block size
/**
* Create a thumbnail of an image. It overscales, centers, and crops to fit the
* target dimensions.
@@ -87,6 +97,23 @@ function hesc($sz) {
function text2html($sz) {
$sectionFmt = function($sz) {
$base = hesc($sz);
$base = preg_replace('~=+(.+)=+~', '<strong>\\1</strong>', $base);
$base = preg_replace('~(https?://[^ \\r\\n\\t]+)~i', '<a href="\\1">\\1</a>', $base);
$btparts = explode('`', $base);
if (count($btparts) > 1 && (count($btparts) % 2)) {
for ($i = 1, $e = count($btparts); $i < $e; $i += 2) {
$btparts[$i] = '<span class="code">'.$btparts[$i].'</span>';
}
$base = implode('', $btparts);
}
return nl2br($base);
};
$identity = function($sz) {
return $sz;
};
@@ -111,22 +138,6 @@ function text2html($sz) {
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);
$btparts = explode('`', $base);
if (count($btparts) > 1 && (count($btparts) % 2)) {
for ($i = 1, $e = count($btparts); $i < $e; $i += 2) {
$btparts[$i] = '<span class="code">'.$btparts[$i].'</span>';
}
}
return $oddEven($btparts, $identity, 'nl2br');
};
$htmlSections = $splitInside('<html>', '</html>', $sz);
return $oddEven($htmlSections, $identity, $sectionFmt);
}
@@ -151,7 +162,6 @@ class CProject {
public $projname;
public $shortdesc = '(no description)';
public $subtag = '';
public $lastupdate = 0;
private $longdesc = '';
private $images = array();
private $downloads = array();
@@ -170,8 +180,6 @@ class CProject {
if ($file[0] == '.') continue;
if ($file == 'README.txt') {
$this->lastupdate = max($this->lastupdate, filectime($this->dir.$file)); // don't count README updates
$this->longdesc = file_get_contents($this->dir.'README.txt');
$matches = array();
if (preg_match('~Written in ([^\\r\\n]+)~', $this->longdesc, $matches)) {
@@ -187,13 +195,7 @@ class CProject {
$this->shortdesc[0] = strtolower($this->shortdesc[0]); // cosmetic lowercase
continue;
}
$this->lastupdate = max(
$this->lastupdate,
filemtime($this->dir.$file),
filectime($this->dir.$file)
);
if (is_image($file)) {
$this->images[] = $file;
} else {
@@ -209,7 +211,7 @@ class CProject {
if (count($this->images)) {
$this->homeimage = mkthumbnail(
$this->dir.$this->images[0],
$this->dir.$this->images[0], //BASEDIR.'wwwroot/srv/'.$this->projname.'_0.'.str_ext($this->images[0]),
null, // raw handle
INDEX_THUMB_W, INDEX_THUMB_H
);
@@ -262,7 +264,7 @@ class CProject {
<p><?=text2html($this->longdesc)?></p>
<?=file_get_contents(BASEDIR.'/footer.htm')?>
<?=file_get_contents(__DIR__.'/footer.htm')?>
<?php if (count($this->downloads)) { ?>
@@ -287,9 +289,6 @@ 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>
<?php } ?>
</div>
<div style="clear:both;"></div>
<?php } ?>
</div>
@@ -316,7 +315,7 @@ function template($title, $content) {
<body>
<div id="container">
<div id="content">
<?=file_get_contents(BASEDIR.'/header.htm')?>
<?=file_get_contents(__DIR__.'/header.htm')?>
<?=$content?>
</div>
</div>
@@ -369,8 +368,6 @@ function buildcommon() {
$handles = array();
$handle_lookup = array();
$alphasort = [];
foreach($projects as $dirname => $projectname) {
$pr = new CProject($dirname, $projectname);
@@ -384,18 +381,6 @@ function buildcommon() {
$handle_lookup[$projectname] = count($handles);
$handles[] = $pr->homeimage;
}
$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
@@ -414,13 +399,9 @@ function buildcommon() {
<!-- }} -->
<?php } ?>
<table id="projtable-main" class="projtable">
<?php foreach ($plist as $i => $pr) { ?>
<tr class="<?=$pr->getClassAttr()?>"
data-sort-mt="-<?=$pr->lastupdate?>"
data-sort-ct="<?=$i?>"
data-sort-al="<?=$alphaidx[$i]?>"
>
<table class="projtable">
<?php foreach ($plist as $pr) { ?>
<tr class="<?=$pr->getClassAttr()?>">
<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>
</td>
@@ -453,30 +434,8 @@ function buildcommon() {
}
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']));
// Perform build tasks
$total = $args[0];
$pos = $args[1];
if ($pos == 0) {
buildcommon();

View File

@@ -1,61 +0,0 @@
#!/bin/bash
set -eu
PHP=/cygdrive/c/bin/php/php.exe
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..."

View File

@@ -1,8 +0,0 @@
[codesite]
title=code.ivysaur.me
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

View File

@@ -1,11 +0,0 @@
<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==&amp;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>

View File

@@ -1 +0,0 @@
<h1><a href="index.html"><div id="ivylogo"></div>code.ivysaur.me</a></h1>

View File

@@ -1,26 +0,0 @@
<p>
It's said that if you're not disgusted by code you wrote six months ago, you've stopped learning.
</p>
<p>
<strong>OVERVIEW</strong>
</p>
<p>
This page contains several assorted spare-time projects, which no longer have any relation. They are listed in roughly chronological order (newest first). <strong>Unless specified otherwise</strong>, you may feel free to use and modify both the binaries and any source code, for any purpose, on the general condition you do not misrepresent who the author is (BSD license).
</p>
<p>
Some of these projects formerly appeared on Google Code <a href="https://code.google.com/p/mappy/">here</a>, but were moved following the discontinuation of the Google Code binary download system.
</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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,173 +0,0 @@
/* 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;
}

View File

@@ -1,8 +0,0 @@
[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

View File

@@ -1,14 +0,0 @@
<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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 B

BIN
static/header.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 436 B

After

Width:  |  Height:  |  Size: 436 B

View File

Before

Width:  |  Height:  |  Size: 233 B

After

Width:  |  Height:  |  Size: 233 B

View File

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 264 B

View File

@@ -33,65 +33,14 @@
};
var get_show_tag = function(tag) {
return function() {
show_tag(tag);
return false;
};
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();
}
});
})();
})();