Compare commits

..

No commits in common. "master" and "v138" have entirely different histories.
master ... v138

22 changed files with 48 additions and 491 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

4
.gitignore vendored
View File

@ -1,4 +0,0 @@
_dist/
sites/*/data/
sites/*/wwwroot/
shields_cache/

6
.hgignore Normal file
View File

@ -0,0 +1,6 @@
mode:regex
^_dist/
^sites/[^/]+/data/
^sites/[^/]+/wwwroot/
^shields_cache/

7
.hgtags Normal file
View File

@ -0,0 +1,7 @@
42a17645b5b21d7fe395767de7fa3e26ee999014 release-r54
0f89ae041c2ee60cc1ea308d047fce816b19c490 release-r64
d4733a95c3428db8722ce0d0350d17bbbabc8720 release-r72
7c92f9e2e4818d74eded59ad516d7d58b4072f8d release-r97
b1426986ff5f265f79d6412c0e81ccc7cae652ff release-r118
2b11aaaad98718025d020c9fbaa451f65d413477 release-r126
36cb5fdcbd0450a32ba9e88f7582a78b0b50db94 release-r132

View File

@ -1,12 +1,10 @@
# codesite
A static site generator for a portfolio website. A static site generator for a portfolio website.
This script was used to generate the https://code.ivysaur.me/ website between 2013 and 2020, when it was replaced by a [teafolio](https://code.ivysaur.me/teafolio) instance. This script is currently in use to generate the code.ivysaur.me website.
Written in PHP, Bash Written in PHP, Bash
## Features =FEATURES=
- Generates static website, minimising server load and decreasing attack surface compared to dynamic server-side PHP - Generates static website, minimising server load and decreasing attack surface compared to dynamic server-side PHP
- Automatic thumbnailing and sprite sheet generation - Automatic thumbnailing and sprite sheet generation
@ -14,30 +12,12 @@ Written in PHP, Bash
- One-click rebuild, one-click deploy - One-click rebuild, one-click deploy
- Parallel generation - Parallel generation
## Changelog =CHANGELOG=
2020-05-24: v157
- Sunset release
- Rewrite `codesite` Git repository history for full public release
- Feature: Add support for autogenerating codesite projects from a Git repository (`update_git_remote.sh`)
- Feature: Support converting a codesite project into a readonly, archive Git repository (`codesite2git`)
- Feature: Support bulk pushing `codesite2git`-converted repositories to a Gitea instance
2018-12-30: v138
- (Private release only)
- Feature: Support `[git-repository]` tags to link to a custom VCS repository
- Feature: Support markdown link syntax
- Feature: Support markdown multiline comments that include code syntax highlight tag
- Enhancement: Support Go subpackages under `[go-get]` tags
- Enhancement: Strip markdown image urls
- Enhancement: Trim leading blank lines
- Fix a cosmetic issue with favicons and document rendering mode in some versions of IE
2017-10-28: v132 2017-10-28: v132
- Fix an issue with not applying project rename redirections in the new URL format - Fix an issue with not applying project rename redirections in the new URL format
- Fix a cosmetic issue with classifying downloads named with numeric strings - Fix a cosmetic issue with classifying downloads named with numeric strings
- Fix a cosmetic issue with truncated sheilds caused by ID collisions - Fix a cosmetic issue with truncated sheilds caused by ID collisions
- [⬇️ code_v132.tar.xz](.dist-archive/code_v132.tar.xz) *(106.49 KiB)*
2017-04-23: v126 2017-04-23: v126
- Breaking: BASEURL is now a mandatory field - Breaking: BASEURL is now a mandatory field
@ -46,7 +26,6 @@ Written in PHP, Bash
- Feature: Use extension-less paths by default (old .html paths still supported via redirect) - Feature: Use extension-less paths by default (old .html paths still supported via redirect)
- Feature: Support `[url]` tags - Feature: Support `[url]` tags
- Enhancement: Cache-busting parameters on homepage thumbnails - Enhancement: Cache-busting parameters on homepage thumbnails
- [⬇️ code_v126.tar.xz](.dist-archive/code_v126.tar.xz) *(106.39 KiB)*
2016-04-19: v118 2016-04-19: v118
- Feature: Classify download artefacts by matching CHANGELOG entry - Feature: Classify download artefacts by matching CHANGELOG entry
@ -54,7 +33,6 @@ Written in PHP, Bash
- Feature: Separate site generation code from site data repositories - Feature: Separate site generation code from site data repositories
- Enhancement: Update supplied CSS normalize script - Enhancement: Update supplied CSS normalize script
- Enhancement: Read parallelism from number of CPUs - Enhancement: Read parallelism from number of CPUs
- [⬇️ code_v118.tar.xz](.dist-archive/code_v118.tar.xz) *(103.18 KiB)*
2015-11-08: v97 2015-11-08: v97
- Feature: Support BBCode b/i/spoiler/entry tags - Feature: Support BBCode b/i/spoiler/entry tags
@ -63,18 +41,15 @@ Written in PHP, Bash
- Feature: Optional blurbs=off, article_header={string}, shields_prefix=true configuration directives - Feature: Optional blurbs=off, article_header={string}, shields_prefix=true configuration directives
- Fix an issue with project update-time detection - Fix an issue with project update-time detection
- Fix a cosmetic issue with whitespace - Fix a cosmetic issue with whitespace
- [⬇️ code_v97.tar.xz](.dist-archive/code_v97.tar.xz) *(107.54 KiB)*
2015-04-05: v72 2015-04-05: v72
- Feature: Support redirecting old project names - Feature: Support redirecting old project names
- Feature: Add file hash in download URLs to prevent filename collisions - Feature: Add file hash in download URLs to prevent filename collisions
- Fix an issue generating spritesheets even if no project images are present - Fix an issue generating spritesheets even if no project images are present
- Don't include `ctime` when estimating project update time - Don't include `ctime` when estimating project update time
- [⬇️ code_v72.tar.xz](.dist-archive/code_v72.tar.xz) *(106.79 KiB)*
2015-04-05: v64 2015-04-05: v64
- Feature: Support sorting projects - Feature: Support sorting projects
- [⬇️ code_v64.tar.xz](.dist-archive/code_v64.tar.xz) *(106.45 KiB)*
2015-04-04: v54 2015-04-04: v54
- Feature: Support multiple code sites - Feature: Support multiple code sites
@ -82,7 +57,6 @@ Written in PHP, Bash
- Fix an issue corrupting URL links with multiple parameters - Fix an issue corrupting URL links with multiple parameters
- Fix a cosmetic issue with page overflow - Fix a cosmetic issue with page overflow
- Fix a cosmetic issue with whitespace on code elements - Fix a cosmetic issue with whitespace on code elements
- [⬇️ code_v54.tar.xz](.dist-archive/code_v54.tar.xz) *(105.79 KiB)*
2014-07-02: v39 2014-07-02: v39
- Feature: Tags - Feature: Tags
@ -92,11 +66,9 @@ Written in PHP, Bash
- Fix a cosmetic issue with image thumbnail backgrounds - Fix a cosmetic issue with image thumbnail backgrounds
- Fix a cosmetic issue with download sort order - Fix a cosmetic issue with download sort order
- Fix a cosmetic issue with page layout - Fix a cosmetic issue with page layout
- [⬇️ code_v39.zip](.dist-archive/code_v39.zip) *(13.11 KiB)*
2013-09-28: v13 2013-09-28: v13
- Initial public source code release - Initial public source code release
- [⬇️ code_v13.zip](.dist-archive/code_v13.zip) *(9.02 KiB)*
2013-09-21: v3 2013-09-21: v3
- Initial deployment - Initial deployment

View File

@ -1,27 +0,0 @@
#!/usr/bin/php
<?php
require __DIR__ . '/lib/bootstrap.php';
function main($args) {
$config = setup_vars();
$total = $args[0];
$pos = $args[1];
// Perform build tasks
if ($pos == 0) {
buildcommon();
if (array_key_exists('redirect', $config)) {
buildredirects( $config['redirect'] );
}
if (array_key_exists('golang-subpackages', $config)) {
buildgosubpackages( $config['golang-subpackages'] );
}
} else {
buildprojects($pos, array_decimate(listprojects(), $total, $pos));
}
}
main(array_slice($_SERVER['argv'], 1));

View File

@ -1,334 +0,0 @@
#!/usr/bin/php
<?php
require __DIR__.'/lib/bootstrap.php';
class CProjectGitExporter extends CProject {
function __construct(string $projdirname, string $projname) {
CProject::__construct($projdirname, $projname);
$this->allowText2Html = false; // Don't produce HTML when processing the download block
}
function ExportAsGit(string $dest) {
// Create destination directory
if (is_dir($dest)) {
throw new Exception("Destination path '{$dest}' already exists");
}
mkdir($dest);
shell_exec('cd '. escapeshellarg($dest).' && git init');
// Parse download information blocks
$this->filterLongDescArea();
// Prepare to start modifying the generated README.md file
$this->longdesc = preg_replace('~\\[url=([^\\]]+?)\\](.+?)\\[/url\\]~m', '[\\2](\\1)', $this->longdesc);
$this->longdesc = str_replace("\xEF\xBB\xBF", "", $this->longdesc); // Remove interior UTF-8 BOM markers
$this->longdesc = str_replace("\r", "", $this->longdesc); // dos2unix
// Add main header and "written in" badge
$lines = explode("\n", $this->longdesc);
$header = ["# ".$this->projname, ""];
if (strlen($this->subtag) > 0) {
$header[] = "![](https://img.shields.io/badge/written%20in-" . rawurlencode($this->subtag) . "-blue)";
$header[] = "";
}
$lines = array_merge($header, $lines);
// Modify some lines to standard markdown format:
foreach($lines as $i => $line) {
// Convert ==HEADERS== to ## Headers
if (strlen($line) > 0 && $line[0] == '=') {
$tmp = rtrim($line, '=');
$indent = substr_count($tmp, '=');
// Normalise the capitalisation for header text
$header_text = substr($tmp, $indent);
if ($header_text != "TODO" && $header_text != "FIXME" && $header_text != "WARNING" && $header_text != "API") {
$header_text = ucwords(strtolower($header_text));
}
// raise markdown-equivalent header level by 1 to compensate for new header
$lines[$i] = $line = str_repeat('#', $indent + 1).' '.$header_text;
}
// Convert multiline single-backtick to multi-backtick
// Heuristic: if there is only a single backtick in the line
if (substr_count($line, '`') == 1) {
$lines[$i] = $line = str_replace('`', "\n```\n", $line);
}
// If the previous line started with a hyphen, and this line didn't, we need an
// extra line separator
if ($i > 0 && strlen($line) > 0 &&
$line[0] != '-' && strlen($lines[$i-1]) > 0 && $lines[$i-1][0] == '-'
) {
$lines[$i] = $line = "\n".$line;
}
}
// Copy all images to a doc/ subdirectory
if (count($this->images) > 0) {
mkdir($dest.'/doc');
foreach($this->images as $img) {
// Normalise some legacy file extension variants while we're here
copy($this->dir.$img, $dest.'/doc/'.str_replace(['.jpeg', '.JPG', '.JPEG'], ['.jpg', '.jpg', '.jpg'], $img));
}
}
// Copy all downloads to a dist-archive/ subdirectory
if (count($this->downloads) > 0) {
mkdir($dest.'/dist-archive');
foreach($this->downloads as $file) {
copy($this->dir.$file, $dest.'/dist-archive/'.$file);
}
if (! $this->downloads_section_was_replaced) {
// Add our own downloads section
$lines[] = $this->renderDownloadsBlock($this->downloads, true);
}
}
// Save final README
file_put_contents($dest.'/README.md', implode("\n", $lines));
// Extra properties file
$ctime = $this->lastupdate - ($this->lifespan * 3600); // Lifespans are measured in hours
if (strlen($this->shortdesc) > 0) {
$this->shortdesc = rtrim($this->shortdesc, '.').'.';
$this->shortdesc[0] = strtoupper($this->shortdesc[0]);
}
file_put_contents($dest.'/.legacy-codesite.toml', "# Converted with codesite2git
project_name=".json_encode($this->projname)."
short_description=".json_encode($this->shortdesc)."
written_in_lang=".json_encode($this->subtag)."
topics=".json_encode($this->tags)."
ctime=".$ctime."
mtime=".$this->lastupdate."
");
// Git commit everything
// Once for the meta with ctime; once for all files with the mtime
$command = (
'cd '. escapeshellarg($dest).' && '.
'git add .legacy-codesite.toml ; '.
'GIT_COMMITTER_DATE="'.date(DATE_ISO8601, $ctime).'" git commit -m "initial meta commit" --date '.escapeshellarg(date(DATE_ISO8601, $ctime)).' ; '.
'git add -A ; '.
'GIT_COMMITTER_DATE="'.date(DATE_ISO8601, $this->lastupdate).'" git commit -m "commit all archived files" --date '.escapeshellarg(date(DATE_ISO8601, $this->lastupdate))
);
//echo $command."\n";
shell_exec($command);
}
public function renderDownloadsBlock($render_downloads, $include_header=false) { // override
if (! count($render_downloads)) {
return;
}
$ret = "\n";
if ($include_header) {
$ret .= "## Download\n\n";
}
foreach($render_downloads as $filename) {
// It's possible to make a general URL that links directly to the raw download endpoint
// But because our markdown is rendered in context of the repo, we can't properly make a relative link
// We could make an absolute link, but that's probably a bad idea w.r.t. any future Git migrations
// Just link to the file in-repo although it won't be a RAW download link
$ret .= "- [⬇️ {$filename}](dist-archive/".rawurlencode($filename).") "; // raw/branch/master/dist-archive/{$filename}
$ret .= "*(".fbytes(filesize($this->dir.$filename)).")*\n";
}
return $ret;
}
}
class Gitea {
protected $url;
protected $org;
protected $token;
public function __construct(string $url, string $org, string $token) {
$this->url = $url;
$this->org = $org;
$this->token = $token;
}
public function repoExists(string $repo): bool {
$resp = @file_get_contents($this->url.'api/v1/repos/'.$this->org.'/'.$repo);
if ($resp === false) {
return false; // not conclusive but it will suffice
}
if (strpos($resp, 'does not exist')) {
return false;
}
$inf = json_decode($resp, true);
if (is_array($inf) && $inf['name'] == $repo) {
return true; // definitely yes
}
throw new \Exception("Couldn't decide whether repo {$repo} exists\n\n".var_export($resp, true));
}
public function createRepo(string $repo) {
$command = ('curl -sS -X POST ' .
escapeshellarg($this->url.'api/v1/admin/users/'.$this->org.'/repos?access_token='.urlencode($this->token)) . ' '.
'-H "accept: application/json" -H "Content-Type: application/json" -d ' . escapeshellarg(json_encode(['name' => $repo]))
);
$code = 0;
$output = [];
exec($command, $output, $code);
if ($code == 0) {
return; // success
}
throw new \Exception("failed to create repository {$repo} (exit code {$code})\n\n".var_export($output, true));
}
public function updateRepoProperties(string $repo, string $description) {
$json_update = [
'archived' => true,
'description' => $description,
// SPECIAL https://code.ivysaur.me/ - don't leave in commit {{{
'has_wiki' => false,
'website' => 'https://code.ivysaur.me/'.$repo,
// }}}
];
$command = ('curl -sS -X PATCH ' .
escapeshellarg($this->url.'api/v1/repos/'.$this->org.'/'.$repo.'?access_token='.urlencode($this->token)) . ' '.
'-H "accept: application/json" -H "Content-Type: application/json" -d ' . escapeshellarg(json_encode($json_update))
);
$code = 0;
$output = [];
exec($command, $output, $code);
if ($code == 0) {
return; // success
}
throw new \Exception("failed to update repository {$repo} properties: (exit code {$code})\n\n".var_export($output, true));
}
public function setRepoTopics(string $repo, array $topics) {
$command = ('curl -sS -X PUT ' .
escapeshellarg($this->url.'api/v1/repos/'.$this->org.'/'.$repo.'/topics?access_token='.urlencode($this->token)) . ' '.
'-H "accept: application/json" -H "Content-Type: application/json" -d ' . escapeshellarg(json_encode(['topics' => $topics]))
);
$code = 0;
$output = [];
exec($command, $output, $code);
if ($code == 0) {
return; // success
}
throw new \Exception("failed to update repository {$repo} topics: (exit code {$code})\n\n".var_export($output, true));
}
public function gitRemoteUrlFor(string $repo): string {
return $this->url.$this->org.'/'.$repo.'.git';
}
}
function codesite2git(string $projdirname, string $projname, string $dest): CProjectGitExporter {
// Parse existing project
$c = new CProjectGitExporter($projdirname, $projname);
// var_dump($c);
$c->ExportAsGit($dest);
return $c;
}
function usage() {
die("Usage:
codesite2git [FLAGS...]
Options:
--single CODESITE_ROOT_PATH PROJECT_DIR_NAME PROJECT_REAL_NAME DEST_DIR
--all CODESITE_ROOT_PATH TEMP_DIR GITEA_URL GITEA_ORG GITEA_AUTH_TOKEN
");
die(1);
}
function main(array $argv) {
if (count($argv) < 2) {
usage();
}
if ($argv[1] == '--single') {
if (count($argv) != 6) {
usage();
}
$config = setup_vars($argv[2]);
codesite2git($argv[3], $argv[4], $argv[5]);
} else if ($argv[1] == "--all") {
if (count($argv) != 7) {
usage();
}
$config = setup_vars($argv[2]);
$repos = glob(BASEDIR.'data/*');
$temp_dir = $argv[3];
$gitea = new Gitea($argv[4], $argv[5], $argv[6]);
foreach($repos as $i => $path) {
$projdir = basename($path);
$reponame = explode('-', $projdir, 2)[1];
echo sprintf("[%3d/%3d] Processing '%s'... ", $i+1, count($repos), $reponame);
// Convert to git
$git_repo_dir = $temp_dir.'/'.$projdir.'-archive.git';
$c = codesite2git($projdir, $reponame, $git_repo_dir);
// Check if Gitea repo already exists
if ($gitea->repoExists($reponame)) {
throw new \Exception("Abandoning process since repo {$reponame} already exists in Gitea - move it out of the source directory first");
}
// Create new Gitea repo
$gitea->createRepo($reponame);
if (! $gitea->repoExists($reponame)) {
throw new \Exception("Created repo {$reponame} successfully but it doesn't seem to exist?");
}
// Add git remote and push
shell_exec(
'cd '.escapeshellarg($git_repo_dir) .' && '.
'git remote add origin '.escapeshellarg($gitea->gitRemoteUrlFor($reponame)).' && '.
'git push origin master'
);
// Set Gitea topics + description
$gitea->updateRepoProperties($reponame, $c->shortdesc);
$gitea->setRepoTopics($reponame, $c->tags);
echo " Done\n";
}
} else {
usage();
}
}
main($_SERVER['argv']);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

View File

@ -2,26 +2,19 @@
class CProject { class CProject {
protected $dir; private $dir;
/**
* @var string $projname
*/
public $projname; public $projname;
/**
* @var string $shortdesc
*/
public $shortdesc = '(no description)'; public $shortdesc = '(no description)';
public $subtag = ''; public $subtag = '';
public $lastupdate = 0; public $lastupdate = 0;
public $numreleases = 0; public $numreleases = 0;
protected $longdesc = ''; private $longdesc = '';
protected $prefix_html = ''; private $prefix_html = '';
protected $images = array(); private $images = array();
protected $downloads = array(); private $downloads = array();
protected $downloads_hashes = array(); private $downloads_hashes = array();
public $downloads_section_was_replaced = false; public $downloads_section_was_replaced = false;
@ -34,8 +27,6 @@ class CProject {
protected $go_get_target = ''; protected $go_get_target = '';
protected $git_repo = ''; protected $git_repo = '';
protected $allowText2Html = true;
public function __construct($dirname, $projname) { public function __construct($dirname, $projname) {
$this->dir = BASEDIR.'data/'.$dirname.'/'; $this->dir = BASEDIR.'data/'.$dirname.'/';
$this->projname = $projname; $this->projname = $projname;
@ -244,9 +235,7 @@ class CProject {
$this->longdesc = substr($this->longdesc, 0, strlen($this->longdesc)-1); // Strip the extra NL we added $this->longdesc = substr($this->longdesc, 0, strlen($this->longdesc)-1); // Strip the extra NL we added
if ($this->allowText2Html) {
$this->longdesc = text2html($this->longdesc); $this->longdesc = text2html($this->longdesc);
}
foreach($known_tags as $tag_name => $tag_idx) { foreach($known_tags as $tag_name => $tag_idx) {
$this->longdesc = str_replace( $this->longdesc = str_replace(
'${{TAG_'.$tag_idx.'}}', '${{TAG_'.$tag_idx.'}}',
@ -255,9 +244,7 @@ class CProject {
); );
} }
if ($this->allowText2Html) {
$this->longdesc = str_replace("</ul>\n<br />", "</ul>", $this->longdesc); $this->longdesc = str_replace("</ul>\n<br />", "</ul>", $this->longdesc);
}
// Skip displaying the global downloads area // Skip displaying the global downloads area
// This flag also indicates that the content has been pre-HTMLified // This flag also indicates that the content has been pre-HTMLified

View File

@ -1,3 +1,4 @@
#!/usr/bin/php
<?php <?php
ini_set('display_errors', 'On'); ini_set('display_errors', 'On');
@ -10,17 +11,12 @@ require __DIR__.'/CProject.php';
define('SHIELDS_CACHE_DIR', __DIR__.'/../shields_cache/'); define('SHIELDS_CACHE_DIR', __DIR__.'/../shields_cache/');
/** function main($args) {
* Set up global defines for a given codesite project $basedir = './';
* Should be called once we have the root path for a codesite project. $total = $args[0];
* $pos = $args[1];
*/
function setup_vars(string $basedir="./"): array {
// Parse configuration // Parse configuration
if (! is_file($basedir.'config.ini')) {
die("[FATAL] Non-file '${basedir}config.ini'!\n");
}
$config = @parse_ini_file( $config = @parse_ini_file(
$basedir . 'config.ini', $basedir . 'config.ini',
@ -29,7 +25,7 @@ function setup_vars(string $basedir="./"): array {
); );
if ($config === false) { if ($config === false) {
die("[FATAL] Couldn't load '${basedir}config.ini'!\n"); die("[FATAL] Couldn't load '${basedir}/config.ini'!\n");
} }
define('BASEDIR', $basedir); define('BASEDIR', $basedir);
@ -43,5 +39,19 @@ function setup_vars(string $basedir="./"): array {
define('ARTICLE_HEADER', (isset($config['codesite']['article_header']) ? $config['codesite']['article_header'] : 'ABOUT') ); define('ARTICLE_HEADER', (isset($config['codesite']['article_header']) ? $config['codesite']['article_header'] : 'ABOUT') );
define('SHIELDS_PREFIX', isset($config['codesite']['shields_prefix'])); define('SHIELDS_PREFIX', isset($config['codesite']['shields_prefix']));
return $config; // Perform build tasks
if ($pos == 0) {
buildcommon();
if (array_key_exists('redirect', $config)) {
buildredirects( $config['redirect'] );
} }
if (array_key_exists('golang-subpackages', $config)) {
buildgosubpackages( $config['golang-subpackages'] );
}
} else {
buildprojects($pos, array_decimate(listprojects(), $total, $pos));
}
}
main(array_slice($_SERVER['argv'], 1));

View File

@ -96,7 +96,7 @@ function fbytes($size, $suffixes='B|KiB|MiB|GiB|TiB') {
array_shift($sxlist); array_shift($sxlist);
$size /= 1024; $size /= 1024;
} }
return number_format($size, 2).' '.array_shift($sxlist); return number_format($size, 2).array_shift($sxlist);
} }
function str_ext($sz) { function str_ext($sz) {

View File

@ -40,7 +40,7 @@ buildsite() {
local threadcount=$(numcpus) local threadcount=$(numcpus)
for i in $(seq 0 "$threadcount") ; do for i in $(seq 0 "$threadcount") ; do
"${APP_DIR}/build-worker" "$threadcount" "$i" & "${APP_DIR}/lib/bootstrap.php" "$threadcount" "$i" &
done done
wait wait

View File

@ -1,60 +0,0 @@
#!/bin/bash
#
# This script updates/rebuilds a codesite directory from a Git repository.
#
set -eu
main() {
if [[ $# -ne 3 ]] ; then
echo "Usage: update_git_remote DATA_DIR GIT_REMOTE_URI EXTRA_CONTENT" >&2
exit 1
fi
local datadir="$1"
local gitremote="$2"
local extra="${3:-}"
#
echo "Updating ${datadir}..."
if [[ ! -d $datadir ]] ; then
mkdir $datadir
fi
local clone=$(mktemp -d)
(
cd "${clone}"
git clone "${gitremote}" .
)
cp "${clone}/README.md" "${datadir}/README.txt"
rm -fr "${clone}"
# Ensure LF endings
sed -i 's/\x0D$//' "${datadir}/README.txt"
# Remove all shields (codesite inserts its own)
sed -i /shields.io/d "${datadir}/README.txt"
# Remove top-level header (codesite inserts its own)
sed -i -re '/^#([^#])/d' "${datadir}/README.txt"
# Remove leading blank lines (since we removed the top-level header)
sed -i '/./,$!d' "${datadir}/README.txt"
# Convert headings from github-flavored markdown to codesite style (\U for Uppercase)
sed -i -re 's/^## (.+)/=\U\1=/' "${datadir}/README.txt"
# Add extra metadata so that codesite generator can link the repository
echo "" >> "${datadir}/README.txt"
echo "[git]${gitremote}[/git]" >> "${datadir}/README.txt"
# Add any extra per-repository metadata, on a line after the description
if [[ -n "${extra}" ]] ; then
sed -i 3i"${extra}" "${datadir}/README.txt"
fi
}
main "$@"