diff --git a/code/DocumentationViewer.php b/code/DocumentationViewer.php index b9be3c7..9e333da 100755 --- a/code/DocumentationViewer.php +++ b/code/DocumentationViewer.php @@ -6,11 +6,7 @@ * Reads the bundled markdown files from doc/ folders and displays output in * a formatted page * - * @todo - * - We should move away from relying on DebugViewer. We could even use the actual - * standard template system for the layout - * - * - Abstract html / css out from DebugViewer + * @todo Tidy up template / styling * * @package sapphiredocs */ @@ -39,9 +35,11 @@ class DocumentationViewer extends Controller { $this->writeHeader(); $base = Director::baseURL(); + $readme = ($this->readmeExists('sapphire')) ? "Read Me" : false; + // write the main content (sapphire) on the left - echo "
"; - echo "

Sapphire

"; + echo "
"; + echo "

sapphire $readme

"; $this->generateNestedTree('sapphire'); @@ -50,6 +48,9 @@ class DocumentationViewer extends Controller { $modules = scandir(BASE_PATH); + // modules which are not documented + $undocumented = array(); + // generate a list of module documentation (not core) if($modules) { foreach($modules as $module) { @@ -57,51 +58,37 @@ class DocumentationViewer extends Controller { $ignored_modules = array('sapphire', 'assets', 'themes'); if(!in_array($module, $ignored_modules) && !in_array($module, self::$ignored_files) && is_dir(BASE_PATH .'/'. $module)) { - echo "

". $module ."

"; // see if docs folder is present $subfolders = scandir(BASE_PATH .'/'. $module); if($subfolders && in_array('doc', $subfolders)) { + $readme = ($filename = $this->readmeExists($module)) ? "Read Me" : false; + echo "

". $module .' '. $readme."

"; $this->generateNestedTree($module); + echo "
"; } else { - echo "

No Documentation For Module

"; + $undocumented[] = $module; } - echo "
"; + } } } // for each of the modules. Display them here - echo "
"; + echo "
"; + + if($undocumented) { + echo "

Undocumented Modules: "; + echo implode(', ', $undocumented); + } + $this->writeFooter(); } - /** - * @todo - This is nasty, ripped out of DebugView. - */ - function writeHeader() { - echo ' - - - ' . htmlentities($_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI']) . ' - - - -

SilverStripe
-
-

SilverStripe Documentation

- -
'; - } - function writeFooter() { - echo ""; - } - /** * Parse a given individual markdown page * @@ -116,7 +103,7 @@ class DocumentationViewer extends Controller { if(!stripos($class, '.md')) $class .= '.md'; - $this->writeHeader(); + $this->writeHeader($class, $module); $base = Director::baseURL(); @@ -140,6 +127,63 @@ class DocumentationViewer extends Controller { $this->writeFooter(); } + /** + * @todo - This is nasty, ripped out of DebugView. + */ + function writeHeader($class = "", $module = "") { + $breadcrumbs = false; + if($module) { + $parts = array(); + $parts[] = "Documentation Home"; + $parts[] = "$module"; + + if($class) $parts[] = $this->formatStringForTitle($class); + + $breadcrumbs = implode(" » ", $parts); + $breadcrumbs = ''; + } + + echo ' + + + ' . htmlentities($_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI']) . ' + + + +
+ + '; + } + + function writeFooter() { + echo "
"; + } + + /** + * Work out if a module contains a readme + * + * @param String - Module to check + * @return bool|String - of path + */ + private function readmeExists($module) { + $children = scandir(BASE_PATH.'/'.$module); + + $readmeOptions = array('readme', 'readme.md', 'readme.txt'); + + if($children) { + foreach($children as $i => $file) { + if(in_array(strtolower($file), $readmeOptions)) return $file; + } + } + + return false; + } + + /** * Find a documentation page within a given module. * @@ -196,13 +240,13 @@ class DocumentationViewer extends Controller { if($handle) { while (false !== ($file = readdir($handle))) { if(!in_array($file, self::$ignored_files)) { - $newPath = $path.$file; - + $newPath = $path.'/'.$file; + // if the file is a dir nest the pages if(is_dir($newPath)) { // if this has a number - echo "
  • ". $this->formatStringForTitle($file) ."
  • "; + echo "
  • ". $this->formatStringForTitle($file) ."
  • "; $this->recursivelyGenerateTree($newPath, $module); } @@ -234,6 +278,9 @@ class DocumentationViewer extends Controller { // change - to spaces $title = str_ireplace('-', ' ', $title); + // remove extension + $title = str_ireplace('.md', ' ', $title); + return $title; } } \ No newline at end of file diff --git a/css/DocumentationViewer.css b/css/DocumentationViewer.css index 153343f..7993682 100644 --- a/css/DocumentationViewer.css +++ b/css/DocumentationViewer.css @@ -6,23 +6,25 @@ body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding: 0;} -html { background: #eee;} -body { font: 14px/1.1 Helvetica,Arial,sans-serif; color: #333; } +html { background: #f4f4f4;} +body { font: 14px/1.1 Arial,sans-serif; color: #444; } +a { color: #1389ce; text-decoration: none; } + a:hover { text-decoration: underline;} p { font-size: 14px; - line-height: 21px; - margin-bottom: 21px; + line-height: 22px; + margin-bottom: 22px; } -ul { margin: 0 0 21px 21px; } - li { font-size: 14px; line-height: 21px;} +ul { margin: 8px 16px 20px 20px; } + li { font-size: 12px; line-height: 18px; margin-bottom: 8px;} -h1 { font-size: 18px; margin-bottom: 18px; } -h2 { font-size: 16px; margin-bottom: 18px; } -h3 { font-size: 14px; margin-bottom: 18px; } -h4 { font-size: 12px; margin-bottom: 9px; } +h1 { font-size: 24px; margin-bottom: 18px; } +h2 { font-size: 18px; margin-bottom: 16px; } +h3 { font-size: 16px; margin-bottom: 16px; } +h4 { font-size: 14px; margin-bottom: 8px; } pre { margin-bottom: 18px; @@ -32,92 +34,50 @@ pre { padding: 12px; } -/* Header Banner */ -.info { - border:1px solid #bbb; - border-width: 1px 0; - background-color:#ccdef3; - padding: 12px; - margin-bottom: 18px; -} - - .info h1 { - margin: 0; - padding: 0; - color: #333; - font-size: 30px; - letter-spacing: -2px; - } +#Container { width: 860px; margin: 20px auto; padding: 20px; background: #fff; overflow: hidden; } - .info h3 { - margin: 4px 0; - color: #333; - font-size: 14px; - } +#Header { border-bottom: 3px solid #535360; padding-top: 10px; margin-bottom: 30px; } + #Header h1 { margin-bottom: 9px;} + #Header h1 a { text-decoration: none; font-size: 30px; color: #333; letter-spacing: -1px;} - .info p { - color: #484f57; - margin: 0; - - } - -.header { - margin:0; - background-color:#666673; - text-align: right; - font-size: 12px; - padding: 8px 12px; - color: #fff; - background-image:url(../../cms/images/mainmenu/top-bg.gif); -} - -.trace { padding:6px 12px; } -.trace li { font-size:14px; margin:6px 0; } - -pre span { color:#999;} -pre .error { color:#f00; } - -/* Status Box */ -.status { - padding:10px 20px 10px 40px; - margin-bottom: 12px; -} - .status h2 { margin: 0; } - .pass { - color:#006600; - background:#E2F9E3 url(../../cms/images/alert-good.gif) no-repeat scroll 7px 50%; - border:1px solid #8DD38D; - } - .fail { - color:#C80700; - background:#FFE9E9 url(../../cms/images/alert-bad.gif) no-repeat scroll 7px 50%; - border:1px solid #C80700; - } - .pending { - background: #fefcc5; - border: 1px solid #dedc51; - } - -.buildCompleted { display: none; } - -.failure span { color:#C80700; font-weight:bold; } - + #Header .breadcrumbs { font-size: 12px; } #LeftColumn { - width: 60%; + width: 600px; float: left; } #RightColumn { - width: 40%; + width: 240px; float: right; } -.box { - background: #fff; - padding: 12px; - margin: 0 12px 12px 12px; - border: 1px solid #ddd; +#Home #LeftColumn { width: 500px; } +#Home #RightColumn { width: 340px; } +#Home .box { + margin: 0 12px 12px 0px; + border: 1px solid #d8d8d8; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; } + .box h2 { + background: #535360; + border: 1px solid #535360; + -moz-border-top-radius: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + padding: 6px 8px; + font-weight: 500; + color: #fff; + font-size: 13px; + } + .box h2 a { + background: url(../images/readme.png) no-repeat right center; + padding: 2px 20px 0 0; + font-size: 11px; + color: #fff; + display: block; + float: right; + } #RightColumn .box { margin: 0 12px 12px 0; } @@ -130,6 +90,19 @@ pre .error { color:#f00; } } .box ul.tree li { list-style: none; - font-size: 12px; } - + .box ul.tree li.folder { + background: #d5eefd; + font-size: 12px; + color: #29688c; + margin-bottom: 9px; + border: 1px solid #d5eefd; + padding: 2px 6px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + } +.undocumentedModules { + clear: both; + padding-top: 10px; + font-style: italic; +} \ No newline at end of file diff --git a/doc/Writing-Documentation.md b/doc/Writing-Documentation.md new file mode 100644 index 0000000..5e0a8a8 --- /dev/null +++ b/doc/Writing-Documentation.md @@ -0,0 +1,28 @@ +# Writing Documentation # + + +Your documentation needs to go in the specific modules doc folder which it refers mostly too. For example if you want to document +a feature of your custom module 'MyModule' you need to create markdown files in mymodule/doc/. + +The files have to end with the __.md__ extension. The documentation viewer will automatically replace hyphens (-) with spaces (since you cannot +have spaces easily in some file systems). + +## Syntax ## +This uses a customized markdown extra parser. To view the syntax for page formatting check out [http://daringfireball.net/projects/markdown/syntax][Daring Fireball] + + +## Creating Hierarchy ## + +The document viewer supports folder structure. There is no limit on depth or number of sub categories you can create. + +## Customizing Page Order ## + +Sometimes you will have pages which you want at the top of the documentation viewer summary. Pages like Getting-Started will come after Advanced-Usage +due to the default alphabetical ordering. + +To handle this you can use a number prefix for example __01-My-First-Folder__ which would be the first folder in the list. + +DocumentationViewer will remove the __01-__ from the name as well so you don't need to worry about labels for your folders with numbers. It will be +outputted in the front end as __My First Folder__ + + \ No newline at end of file diff --git a/images/readme.png b/images/readme.png new file mode 100755 index 0000000..813f712 Binary files /dev/null and b/images/readme.png differ