Created
September 3, 2011 08:05
-
-
Save xwero/1190837 to your computer and use it in GitHub Desktop.
Ugling: static site generator with phing (the basics)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<project name="Ugling" basedir="." default="loop"> | |
<!-- set variables to use in the tasks --> | |
<property name="dir.raw.content" value="content" /> | |
<property name="dir.www.content" value="online" /> | |
<property name="template.base" value="templates/base.html" /> | |
<taskdef name="markdown" classname="phing.tasks.ext.MarkdownTask" /> | |
<!-- phing gotcha: if you don't put a foreach in a target you get an error --> | |
<target name="loop"> | |
<foreach param="filename" absparam="absfilename" target="single"> | |
<fileset dir="${dir.raw.content}"> | |
<include name="*.md"/> | |
<include name="**/*.md"/> | |
</fileset> | |
</foreach> | |
</target> | |
<target name="single" description="render a single markdown file to HTML and add template"> | |
<php function="str_replace" returnProperty="file"> | |
<param value=".md"/> | |
<param value=""/> | |
<param value="${filename}"/> | |
</php> | |
<markdown file="${absfilename}" destination="${dir.www.content}/${file}.html" /> | |
<copy file="${dir.www.content}/${file}.html" tofile="${dir.www.content}/${file}2.html"/> | |
<!-- phing gotcha: expression attribute doen't process the variables --> | |
<php function="file_get_contents" returnProperty="pagecontent"> | |
<param value="${dir.www.content}/${file}.html"/> | |
</php> | |
<php function="file_get_contents" returnProperty="rawtemplate"> | |
<param value="${template.base}"/> | |
</php> | |
<php function="str_replace" returnProperty="templatecontent"> | |
<param value="[CONTENT]"/> | |
<param value="${pagecontent}"/> | |
<param value="${rawtemplate}"/> | |
</php> | |
<php function="file_put_contents"> | |
<param value="${dir.www.content}/${file}2.html"/> | |
<param value="${templatecontent}"/> | |
</php> | |
<move file="${dir.www.content}/${file}2.html" tofile="${dir.www.content}/${file}.html" overwrite="true"/> | |
</target> | |
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require_once 'phing/Task.php'; | |
require_once 'phing/util/FileUtils.php'; | |
require_once 'System.php'; | |
require_once "phing/tasks/ext/markdown/markdown.php"; | |
class MarkdownTask extends Task { | |
/** | |
* @var string Taskname for logger | |
*/ | |
protected $taskName = 'Markdown'; | |
/** | |
* Result format, defaults to "html". | |
* @see $supportedFormats for all possible options | |
* | |
* @var string | |
*/ | |
protected $format = 'html'; | |
/** | |
* Input file in markdown format. | |
* Required | |
* | |
* @var string | |
*/ | |
protected $file = null; | |
/** | |
* Output file or directory. May be omitted. | |
* When it ends with a slash, it is considered to be a directory | |
* | |
* @var string | |
*/ | |
protected $destination = null; | |
protected $filesets = array(); // all fileset objects assigned to this task | |
protected $mapperElement = null; | |
/** | |
* all filterchains objects assigned to this task | |
* | |
* @var array | |
*/ | |
protected $filterChains = array(); | |
/** | |
* mode to create directories with | |
* | |
* @var integer | |
*/ | |
protected $mode = 0755; | |
/** | |
* Only render files whole source files are newer than the | |
* target files | |
* | |
* @var boolean | |
*/ | |
protected $uptodate = false; | |
/** | |
* The main entry point method. | |
* | |
* @return void | |
*/ | |
public function main() | |
{ | |
if (count($this->filterChains)) { | |
$this->fileUtils = new FileUtils(); | |
} | |
if ($this->file != '') { | |
$file = $this->file; | |
$targetFile = $this->getTargetFile($file, $this->destination); | |
$this->render($file, $targetFile); | |
return; | |
} | |
if (!count($this->filesets)) { | |
throw new BuildException( | |
'"file" attribute or "fileset" subtag required' | |
); | |
} | |
// process filesets | |
$mapper = null; | |
if ($this->mapperElement !== null) { | |
$mapper = $this->mapperElement->getImplementation(); | |
} | |
$project = $this->getProject(); | |
foreach ($this->filesets as $fs) { | |
$ds = $fs->getDirectoryScanner($project); | |
$fromDir = $fs->getDir($project); | |
$srcFiles = $ds->getIncludedFiles(); | |
foreach ($srcFiles as $src) { | |
$file = new PhingFile($fromDir, $src); | |
if ($mapper !== null) { | |
$results = $mapper->main($file); | |
if ($results === null) { | |
throw new BuildException( | |
sprintf( | |
'No filename mapper found for "%s"', | |
$file | |
) | |
); | |
} | |
$targetFile = reset($results); | |
} else { | |
$targetFile = $this->getTargetFile($file, $this->destination); | |
} | |
$this->render($file, $targetFile); | |
} | |
} | |
} | |
/** | |
* Renders a single file and applies filters on it | |
* | |
* @param string $tool conversion tool to use | |
* @param string $source markdown source file | |
* @param string $targetFile target file name | |
* | |
* @return void | |
*/ | |
protected function render($source, $targetFile) | |
{ | |
if (count($this->filterChains) == 0) { | |
return $this->renderFile($source, $targetFile); | |
} | |
$tmpTarget = tempnam(sys_get_temp_dir(), 'tmp-'); | |
$this->renderFile($source, $tmpTarget); | |
$this->fileUtils->copyFile( | |
new PhingFile($tmpTarget), | |
new PhingFile($targetFile), | |
true, false, $this->filterChains, | |
$this->getProject(), $this->mode | |
); | |
unlink($tmpTarget); | |
} | |
/** | |
* Renders a single file with the markdown tool. | |
* | |
* @param string $tool conversion tool to use | |
* @param string $source markdown source file | |
* @param string $targetFile target file name | |
* | |
* @return void | |
* | |
* @throws BuildException When the conversion fails | |
*/ | |
protected function renderFile($source, $targetFile) | |
{ | |
if ($this->uptodate && file_exists($targetFile) | |
&& filemtime($source) <= filemtime($targetFile) | |
) { | |
//target is up to date | |
return; | |
} | |
//work around a bug in php by replacing /./ with / | |
$targetDir = str_replace('/./', '/', dirname($targetFile)); | |
if (!is_dir($targetDir)) { | |
mkdir($targetDir, $this->mode, true); | |
} | |
$arOutput = Markdown(file_get_contents($source)); | |
$retval = file_put_contents($targetFile,$arOutput); | |
if ( ! $retval) { | |
$this->log('File not rendered.', Project::MSG_INFO); | |
throw new BuildException('Rendering markdown failed'); | |
} | |
$this->log('File rendered.', Project::MSG_DEBUG); | |
} | |
/** | |
* Determines and returns the target file name from the | |
* input file and the configured destination name. | |
* | |
* @param string $file Input file | |
* @param string $destination Destination file or directory name, | |
* may be null | |
* | |
* @return string Target file name | |
* | |
* @uses $format | |
* @uses $targetExt | |
*/ | |
public function getTargetFile($file, $destination = null) | |
{ | |
if ($destination != '' | |
&& substr($destination, -1) !== '/' | |
&& substr($destination, -1) !== '\\' | |
) { | |
return $destination; | |
} | |
if (strtolower(substr($file, -3)) == '.md') { | |
$file = substr($file, 0, -3); | |
} | |
return $destination . $file . '.' . $this->format; | |
} | |
/** | |
* The setter for the attribute "file" | |
* | |
* @param string $file Path of file to render | |
* | |
* @return void | |
*/ | |
public function setFile($file) | |
{ | |
$this->file = $file; | |
} | |
/** | |
* The setter for the attribute "destination" | |
* | |
* @param string $destination Output file or directory. When it ends | |
* with a slash, it is taken as directory. | |
* | |
* @return void | |
*/ | |
public function setDestination($destination) | |
{ | |
$this->destination = $destination; | |
} | |
/** | |
* The setter for the attribute "uptodate" | |
* | |
* @param string $uptodate True/false | |
* | |
* @return void | |
*/ | |
public function setUptodate($uptodate) | |
{ | |
$this->uptodate = (boolean)$uptodate; | |
} | |
/** | |
* Nested creator, creates a FileSet for this task | |
* | |
* @return object The created fileset object | |
*/ | |
public function createFileSet() | |
{ | |
$num = array_push($this->filesets, new FileSet()); | |
return $this->filesets[$num-1]; | |
} | |
/** | |
* Nested creator, creates one Mapper for this task | |
* | |
* @return Mapper The created Mapper type object | |
* | |
* @throws BuildException | |
*/ | |
public function createMapper() | |
{ | |
if ($this->mapperElement !== null) { | |
throw new BuildException( | |
'Cannot define more than one mapper', $this->location | |
); | |
} | |
$this->mapperElement = new Mapper($this->project); | |
return $this->mapperElement; | |
} | |
/** | |
* Creates a filterchain, stores and returns it | |
* | |
* @return FilterChain The created filterchain object | |
*/ | |
public function createFilterChain() | |
{ | |
$num = array_push($this->filterChains, new FilterChain($this->project)); | |
return $this->filterChains[$num-1]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment