diff --git a/README.md b/README.md index e49258e8..a7c88949 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ![license](https://img.shields.io/github/license/pattern-lab/patternlab-php-core.svg) -[![Packagist](https://img.shields.io/packagist/v/pattern-lab/core.svg)](https://packagist.org/packages/pattern-lab/core) [![Gitter](https://img.shields.io/gitter/room/pattern-lab/php.svg)](https://gitter.im/pattern-lab/php) +[![Gitter](https://img.shields.io/gitter/room/pattern-lab/php.svg)](https://gitter.im/pattern-lab/php) # Pattern Lab Core diff --git a/composer.json b/composer.json index 1deda66d..da40fa12 100644 --- a/composer.json +++ b/composer.json @@ -5,11 +5,21 @@ "homepage": "http://patternlab.io", "license": "MIT", "authors": [ + { + "name": "Evan Lovely", + "homepage": "http://evanlovely.com", + "role": "Lead Developer" + }, + { + "name": "Salem Ghoweri", + "homepage": "https://github.com/sghoweri", + "role": "Developer" + }, { "name": "Dave Olsen", "email": "dmolsen@gmail.com", "homepage": "http://dmolsen.com", - "role": "Lead Developer" + "role": "Former Lead Developer" }, { "name": "Brad Frost", @@ -30,6 +40,7 @@ "require": { "php": ">=5.4", "alchemy/zippy": "^0.3", + "doctrine/collections": "1.4.0", "kevinlebrun/colors.php": "^1.0", "michelf/php-markdown": "^1.6", "seld/jsonlint": "^1.0", diff --git a/src/PatternLab/Builder.php b/src/PatternLab/Builder.php index a869e329..104fe9a6 100644 --- a/src/PatternLab/Builder.php +++ b/src/PatternLab/Builder.php @@ -29,77 +29,118 @@ use \Symfony\Component\Finder\Finder; class Builder { - + /** * When initializing the Builder class make sure the template helper is set-up */ public function __construct() { - + // set-up the pattern engine PatternEngine::init(); - + // set-up the various attributes for rendering templates Template::init(); - + } - + /** * Generates the annotations js file */ protected function generateAnnotations() { - + // set-up the dispatcher $dispatcherInstance = Dispatcher::getInstance(); - + // note the start of the operation $dispatcherInstance->dispatch("builder.generateAnnotationsStart"); - + // default var $publicDir = Config::getOption("publicDir"); - + // encode the content so it can be written out $json = json_encode(Annotations::get()); - + // make sure annotations/ exists if (!is_dir($publicDir."/annotations")) { mkdir($publicDir."/annotations"); } - + // write out the new annotations.js file file_put_contents($publicDir."/annotations/annotations.js","var comments = ".$json.";"); - + // note the end of the operation $dispatcherInstance->dispatch("builder.generateAnnotationsEnd"); - + } - + /** * Generates the data that powers the index page */ protected function generateIndex() { - - // bomb if missing index.html + + /** + * Handle missing index.html. Solves https://github.com/drupal-pattern-lab/patternlab-php-core/issues/14 + * Could also be used to re-add missing styleguidekit assets with a few edits? + * + * 1. @TODO: Figure out a better way to future-proof path resolution for styleguidekit `dist` folder + * 2. Recusirively copy files from styleguidekit to publicDir via https://stackoverflow.com/a/7775949 + * 3. Make sure we only try to create new directories if they don't already exist + * 4. Only copy files if they are missing (vs changed, etc) + */ if (!file_exists(Config::getOption("publicDir")."/index.html")) { $index = Console::getHumanReadablePath(Config::getOption("publicDir")).DIRECTORY_SEPARATOR."index.html"; - Console::writeError("".$index." is missing. grab a copy from your StyleguideKit..."); + Console::writeWarning($index . " is missing. No biggie. Grabbing a fresh copy from your StyleguideKit..."); + + $baseDir = Config::getOption("baseDir") . '/vendor'; + $finder = new Finder(); + + // Locate the current theme's styleguidekit assets via the patternlab-styleguidekit `type` in composer.json + $finder->files()->name("composer.json")->in($baseDir)->contains('patternlab-styleguidekit')->sortByName(); + + foreach ($finder as $file) { + $src = dirname($file->getRealPath()) . DIRECTORY_SEPARATOR . 'dist'; /* [1] */ + $dest= Config::getOption("publicDir"); + + if (is_dir($src)){ + + if(!is_dir($dest)) { + mkdir($dest, 0755); + } + + foreach ( /* [2] */ + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($src, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item + ) { + if ($item->isDir()) { + if(!is_dir($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName())) { /* [3] */ + mkdir($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName()); + } + } else { + if(!file_exists($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName())) { /* [4] */ + copy($item, $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName()); + } + } + } + } + } } - + // set-up the dispatcher $dispatcherInstance = Dispatcher::getInstance(); - + // note the start of the operation $dispatcherInstance->dispatch("builder.generateIndexStart"); - + // default var $dataDir = Config::getOption("publicDir")."/styleguide/data"; - + // double-check that the data directory exists if (!is_dir($dataDir)) { FileUtil::makeDir($dataDir); } - + $output = ""; - + // load and write out the config options $config = array(); $exposedOptions = Config::getOption("exposedOptions"); @@ -107,7 +148,7 @@ protected function generateIndex() { $config[$exposedOption] = Config::getOption($exposedOption); } $output .= "var config = ".json_encode($config).";\n"; - + // load the ish Controls $ishControls = array(); $controlsToHide = array(); @@ -119,24 +160,24 @@ protected function generateIndex() { } $ishControls["ishControlsHide"] = $controlsToHide; $output .= "var ishControls = ".json_encode($ishControls).";\n"; - + // load and write out the items for the navigation $niExporter = new NavItemsExporter(); $navItems = $niExporter->run(); $output .= "var navItems = ".json_encode($navItems).";\n"; - + // load and write out the items for the pattern paths $patternPaths = array(); $ppdExporter = new PatternPathDestsExporter(); $patternPaths = $ppdExporter->run(); $output .= "var patternPaths = ".json_encode($patternPaths).";\n"; - + // load and write out the items for the view all paths $viewAllPaths = array(); $vapExporter = new ViewAllPathsExporter(); $viewAllPaths = $vapExporter->run($navItems); $output .= "var viewAllPaths = ".json_encode($viewAllPaths).";\n"; - + // gather plugin package information $packagesInfo = array(); $componentDir = Config::getOption("componentDir"); @@ -167,27 +208,37 @@ protected function generateIndex() { } } $output .= "var plugins = ".json_encode($packagesInfo).";"; - + // write out the data file_put_contents($dataDir."/patternlab-data.js",$output); - + // Structuring all the same data that went into `patternlab-data.js` and putting it into `patternlab-data.json` too + $allPlData = array( + 'config' => $config, + 'ishControls' => $ishControls, + 'navItems' => $navItems, + 'patternPaths' => $patternPaths, + 'viewAllPaths' => $viewAllPaths, + 'plugins' => $packagesInfo, + ); + file_put_contents($dataDir."/patternlab-data.json", json_encode($allPlData)); + // note the end of the operation $dispatcherInstance->dispatch("builder.generateIndexEnd"); - + } - + /** * Generates all of the patterns and puts them in the public directory * @param {Array} various options that might affect the export. primarily the location. */ protected function generatePatterns($options = array()) { - + // set-up the dispatcher $dispatcherInstance = Dispatcher::getInstance(); - + // note the beginning of the operation $dispatcherInstance->dispatch("builder.generatePatternsStart"); - + // set-up common vars $exportFiles = (isset($options["exportFiles"]) && $options["exportFiles"]); $exportDir = Config::getOption("exportDir"); @@ -197,66 +248,66 @@ protected function generatePatterns($options = array()) { $suffixRendered = Config::getOption("outputFileSuffixes.rendered"); $suffixRaw = Config::getOption("outputFileSuffixes.rawTemplate"); $suffixMarkupOnly = Config::getOption("outputFileSuffixes.markupOnly"); - + // make sure the export dir exists if ($exportFiles && !is_dir($exportDir)) { mkdir($exportDir); } - + // make sure patterns exists if (!is_dir($patternPublicDir)) { mkdir($patternPublicDir); } - + // loop over the pattern data store to render the individual patterns $store = PatternData::get(); foreach ($store as $patternStoreKey => $patternStoreData) { - + if (($patternStoreData["category"] == "pattern") && isset($patternStoreData["hidden"]) && (!$patternStoreData["hidden"])) { - + $path = $patternStoreData["pathDash"]; $pathName = (isset($patternStoreData["pseudo"])) ? $patternStoreData["pathOrig"] : $patternStoreData["pathName"]; - + // modify the pattern mark-up $markup = $patternStoreData["code"]; $markupFull = $patternStoreData["header"].$markup.$patternStoreData["footer"]; $markupEngine = file_get_contents($patternSourceDir."/".$pathName.".".$patternExtension); - + // if the pattern directory doesn't exist create it if (!is_dir($patternPublicDir."/".$path)) { mkdir($patternPublicDir."/".$path); } - + // write out the various pattern files file_put_contents($patternPublicDir."/".$path."/".$path.$suffixRendered.".html",$markupFull); if (!$exportFiles) { file_put_contents($patternPublicDir."/".$path."/".$path.$suffixMarkupOnly.".html",$markup); file_put_contents($patternPublicDir."/".$path."/".$path.$suffixRaw.".".$patternExtension,$markupEngine); } - + } - + } - + // note the end of the operation $dispatcherInstance->dispatch("builder.generatePatternsEnd"); - + } - + /** * Generates the style guide view */ protected function generateStyleguide() { - + // set-up the dispatcher $dispatcherInstance = Dispatcher::getInstance(); - + // note the beginning of the operation $dispatcherInstance->dispatch("builder.generateStyleguideStart"); - + // default var $publicDir = Config::getOption("publicDir"); - + // load the pattern loader $ppdExporter = new PatternPathSrcExporter(); $patternPathSrc = $ppdExporter->run(); @@ -265,56 +316,56 @@ protected function generateStyleguide() { $patternEngineBasePath = PatternEngine::getInstance()->getBasePath(); $patternLoaderClass = $patternEngineBasePath."\Loaders\PatternLoader"; $patternLoader = new $patternLoaderClass($options); - + // check directories i need if (!is_dir($publicDir."/styleguide/")) { mkdir($publicDir."/styleguide/"); } - + if (!is_dir($publicDir."/styleguide/html/")) { mkdir($publicDir."/styleguide/html/"); } - + // grab the partials into a data object for the style guide $ppExporter = new PatternPartialsExporter(); $partials = $ppExporter->run(); - + // add the pattern data so it can be exported $patternData = array(); - + // add the pattern lab specific mark-up $filesystemLoader = Template::getFilesystemLoader(); $stringLoader = Template::getStringLoader(); - + $globalData = Data::get(); $globalData["patternLabHead"] = $stringLoader->render(array("string" => Template::getHTMLHead(), "data" => array("cacheBuster" => $partials["cacheBuster"]))); $globalData["patternLabFoot"] = $stringLoader->render(array("string" => Template::getHTMLFoot(), "data" => array("cacheBuster" => $partials["cacheBuster"], "patternData" => json_encode($patternData)))); $globalData["viewall"] = true; - + $header = $patternLoader->render(array("pattern" => Template::getPatternHead(), "data" => $globalData)); $code = $filesystemLoader->render(array("template" => "viewall", "data" => $partials)); $footer = $patternLoader->render(array("pattern" => Template::getPatternFoot(), "data" => $globalData)); - + $styleGuidePage = $header.$code.$footer; - + file_put_contents($publicDir."/styleguide/html/styleguide.html",$styleGuidePage); - + // note the end of the operation $dispatcherInstance->dispatch("builder.generateStyleguideEnd"); - + } - + /** * Generates the view all pages */ protected function generateViewAllPages() { - + // set-up the dispatcher $dispatcherInstance = Dispatcher::getInstance(); - + // note the beginning of the operation $dispatcherInstance->dispatch("builder.generateViewAllPagesStart"); - + // default vars $patternPublicDir = Config::getOption("patternPublicDir"); $htmlHead = Template::getHTMLHead(); @@ -324,7 +375,7 @@ protected function generateViewAllPages() { $filesystemLoader = Template::getFilesystemLoader(); $stringLoader = Template::getStringLoader(); $globalData = Data::get(); - + // load the pattern loader $ppdExporter = new PatternPathSrcExporter(); $patternPathSrc = $ppdExporter->run(); @@ -333,40 +384,40 @@ protected function generateViewAllPages() { $patternEngineBasePath = PatternEngine::getInstance()->getBasePath(); $patternLoaderClass = $patternEngineBasePath."\Loaders\PatternLoader"; $patternLoader = new $patternLoaderClass($options); - + // make sure view all is set $globalData["viewall"] = true; - + // make sure the pattern dir exists if (!is_dir($patternPublicDir)) { mkdir($patternPublicDir); } - + // add view all to each list $store = PatternData::get(); foreach ($store as $patternStoreKey => $patternStoreData) { - + if ($patternStoreData["category"] == "patternSubtype") { - + // grab the partials into a data object for the style guide $ppExporter = new PatternPartialsExporter(); $partials = $ppExporter->run($patternStoreData["type"],$patternStoreData["name"]); - + if (!empty($partials["partials"])) { - + // add the pattern data so it can be exported $patternData = array(); $patternData["patternPartial"] = "viewall-".$patternStoreData["typeDash"]."-".$patternStoreData["nameDash"]; - + $globalData["patternLabHead"] = $stringLoader->render(array("string" => Template::getHTMLHead(), "data" => array("cacheBuster" => $partials["cacheBuster"]))); $globalData["patternLabFoot"] = $stringLoader->render(array("string" => Template::getHTMLFoot(), "data" => array("cacheBuster" => $partials["cacheBuster"], "patternData" => json_encode($patternData)))); - + // render the parts and join them $header = $patternLoader->render(array("pattern" => $patternHead, "data" => $globalData)); $code = $filesystemLoader->render(array("template" => "viewall", "data" => $partials)); $footer = $patternLoader->render(array("pattern" => $patternFoot, "data" => $globalData)); $viewAllPage = $header.$code.$footer; - + // if the pattern directory doesn't exist create it $patternPath = $patternStoreData["pathDash"]; if (!is_dir($patternPublicDir."/".$patternPath)) { @@ -375,31 +426,31 @@ protected function generateViewAllPages() { } else { file_put_contents($patternPublicDir."/".$patternPath."/index.html",$viewAllPage); } - + } - + } else if (($patternStoreData["category"] == "patternType") && PatternData::hasPatternSubtype($patternStoreData["nameDash"])) { - + // grab the partials into a data object for the style guide $ppExporter = new PatternPartialsExporter(); $partials = $ppExporter->run($patternStoreData["name"]); - + if (!empty($partials["partials"])) { - + // add the pattern data so it can be exported $patternData = array(); $patternData["patternPartial"] = "viewall-".$patternStoreData["nameDash"]."-all"; - + // add the pattern lab specific mark-up - $partials["patternLabHead"] = $stringLoader->render(array("string" => $htmlHead, "data" => array("cacheBuster" => $partials["cacheBuster"]))); - $partials["patternLabFoot"] = $stringLoader->render(array("string" => $htmlFoot, "data" => array("cacheBuster" => $partials["cacheBuster"], "patternData" => json_encode($patternData)))); - + $globalData["patternLabHead"] = $stringLoader->render(array("string" => $htmlHead, "data" => array("cacheBuster" => $partials["cacheBuster"]))); + $globalData["patternLabFoot"] = $stringLoader->render(array("string" => $htmlFoot, "data" => array("cacheBuster" => $partials["cacheBuster"], "patternData" => json_encode($patternData)))); + // render the parts and join them $header = $patternLoader->render(array("pattern" => $patternHead, "data" => $globalData)); $code = $filesystemLoader->render(array("template" => "viewall", "data" => $partials)); $footer = $patternLoader->render(array("pattern" => $patternFoot, "data" => $globalData)); $viewAllPage = $header.$code.$footer; - + // if the pattern directory doesn't exist create it $patternPath = $patternStoreData["pathDash"]; if (!is_dir($patternPublicDir."/".$patternPath)) { @@ -408,16 +459,16 @@ protected function generateViewAllPages() { } else { file_put_contents($patternPublicDir."/".$patternPath."/index.html",$viewAllPage); } - + } - + } - + } - + // note the end of the operation $dispatcherInstance->dispatch("builder.generateViewAllPagesEnd"); - + } - + } diff --git a/src/PatternLab/Config.php b/src/PatternLab/Config.php index b07e90e3..c090348f 100644 --- a/src/PatternLab/Config.php +++ b/src/PatternLab/Config.php @@ -242,10 +242,14 @@ public static function init($baseDir = "", $verbose = true) { self::setExposedOption("cacheBuster"); self::setExposedOption("defaultPattern"); self::setExposedOption("defaultShowPatternInfo"); + self::setExposedOption("patternExtension"); self::setExposedOption("ishFontSize"); self::setExposedOption("ishMaximum"); self::setExposedOption("ishMinimum"); + self::setExposedOption("ishViewportRange"); self::setExposedOption("outputFileSuffixes"); + self::setExposedOption("patternStates"); + self::setExposedOption("theme"); self::setExposedOption("plugins"); } diff --git a/src/PatternLab/Data.php b/src/PatternLab/Data.php index e0da3fc7..75b05654 100644 --- a/src/PatternLab/Data.php +++ b/src/PatternLab/Data.php @@ -125,7 +125,7 @@ public static function gather($options = array()) { $pathName = $file->getPathname(); $pathNameClean = str_replace($sourceDir."/","",$pathName); - if (!$hidden && (($ext == "json") || ($ext == "yaml"))) { + if (!$hidden && (($ext == "json") || ($ext == "yaml") || ($ext == "yml"))) { if ($isListItems === false) { @@ -137,7 +137,7 @@ public static function gather($options = array()) { JSON::lastErrorMsg($pathNameClean,$jsonErrorMessage,$data); } - } else if ($ext == "yaml") { + } else if (($ext == "yaml") || ($ext == "yml")) { $file = file_get_contents($pathName); diff --git a/src/PatternLab/InstallerUtil.php b/src/PatternLab/InstallerUtil.php index 66a3fab5..fcc7fa99 100644 --- a/src/PatternLab/InstallerUtil.php +++ b/src/PatternLab/InstallerUtil.php @@ -349,14 +349,15 @@ protected static function parseComponentList($packageName,$sourceBase,$destinati // iterate over the returned objects foreach ($finder as $file) { - $ext = $file->getExtension(); + $ext = $file->getExtension(); + $pathName = $file->getPathname(); if ($ext == "css") { - $componentTypes["stylesheets"][] = str_replace($sourceBase.$source,$destination,$file->getPathname()); + $componentTypes["stylesheets"][] = str_replace(DIRECTORY_SEPARATOR,"/",str_replace($sourceBase.$source,$destination,$pathName)); } else if ($ext == "js") { - $componentTypes["javascripts"][] = str_replace($sourceBase.$source,$destination,$file->getPathname()); + $componentTypes["javascripts"][] = str_replace(DIRECTORY_SEPARATOR,"/",str_replace($sourceBase.$source,$destination,$pathName)); } else if ($ext == $templateExtension) { - $componentTypes["templates"][] = str_replace($sourceBase.$source,$destination,$file->getPathname()); + $componentTypes["templates"][] = str_replace(DIRECTORY_SEPARATOR,"/",str_replace($sourceBase.$source,$destination,$pathName)); } } diff --git a/src/PatternLab/PatternData.php b/src/PatternLab/PatternData.php index 39129553..3e7ced4e 100644 --- a/src/PatternLab/PatternData.php +++ b/src/PatternLab/PatternData.php @@ -116,16 +116,19 @@ public static function gather($options = array()) { if (!is_dir(Config::getOption("patternSourceDir"))) { Console::writeError("having patterns is important. please make sure you've installed a starterkit and/or that ".Console::getHumanReadablePath(Config::getOption("patternSourceDir"))." exists..."); } - $patternObjects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(Config::getOption("patternSourceDir")), \RecursiveIteratorIterator::SELF_FIRST); - $patternObjects->setFlags(\FilesystemIterator::SKIP_DOTS); + + $patternSourceDir = Config::getOption("patternSourceDir"); + $patternObjects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($patternSourceDir, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS | \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST); // sort the returned objects $patternObjects = iterator_to_array($patternObjects); ksort($patternObjects); - $patternSourceDir = Config::getOption("patternSourceDir"); - - foreach ($patternObjects as $name => $object) { + /** + * @var string $name + * @var \SplFileInfo $object + */ + foreach ($patternObjects as $name => $object) { $ext = $object->getExtension(); $isDir = $object->isDir(); @@ -181,6 +184,7 @@ public static function gather($options = array()) { $event = new PatternDataEvent($options); $dispatcherInstance->dispatch("patternData.lineageHelperEnd",$event); + // dispatch that the pattern state helper is about to start $event = new PatternDataEvent($options); $dispatcherInstance->dispatch("patternData.patternStateHelperStart",$event); diff --git a/src/PatternLab/PatternData/Exporters/DataLinkExporter.php b/src/PatternLab/PatternData/Exporters/DataLinkExporter.php index fdd875eb..9494cd8d 100644 --- a/src/PatternLab/PatternData/Exporters/DataLinkExporter.php +++ b/src/PatternLab/PatternData/Exporters/DataLinkExporter.php @@ -31,16 +31,33 @@ public function __construct($options = array()) { public function run() { foreach ($this->store as $patternStoreKey => $patternStoreData) { - - if ($patternStoreData["category"] == "pattern") { - - if (isset($patternStoreData["pathDash"])) { - $value = "../../patterns/".$patternStoreData["pathDash"]."/".$patternStoreData["pathDash"].".html"; - Data::setOptionLink($patternStoreKey, $value); - } - - } - + + switch ($patternStoreData["category"]) { + // atoms - view all + case "patternType": + if (isset($patternStoreData["pathDash"])) { + $value = "../../patterns/" . $patternStoreData["pathDash"] . "/index.html"; + Data::setOptionLink("viewall-" . $patternStoreData["nameDash"] . "-all", $value); + } + break; + + // atoms/forms - view all + case "patternSubtype": + if (isset($patternStoreData["pathDash"])) { + $value = "../../patterns/" . $patternStoreData["pathDash"] . "/index.html"; + Data::setOptionLink($patternStoreData["partial"], $value); + } + break; + + // atoms/forms/select.mustache + case "pattern": + if (isset($patternStoreData["pathDash"])) { + $value = "../../patterns/" . $patternStoreData["pathDash"] . "/" . $patternStoreData["pathDash"] . ".html"; + Data::setOptionLink($patternStoreKey, $value); + } + break; + } + } } diff --git a/src/PatternLab/PatternData/Exporters/PatternPartialsExporter.php b/src/PatternLab/PatternData/Exporters/PatternPartialsExporter.php index 14d7ab08..cf441746 100644 --- a/src/PatternLab/PatternData/Exporters/PatternPartialsExporter.php +++ b/src/PatternLab/PatternData/Exporters/PatternPartialsExporter.php @@ -47,8 +47,20 @@ public function run($type = "", $subtype = "") { $suffixRendered = Config::getOption("outputFileSuffixes.rendered"); foreach ($this->store as $patternStoreKey => $patternStoreData) { - - if (($patternStoreData["category"] == "pattern") && isset($patternStoreData["hidden"]) && (!$patternStoreData["hidden"]) && (!$patternStoreData["noviewall"]) && ($patternStoreData["depth"] > 1) && (!in_array($patternStoreData["type"],$this->styleGuideExcludes))) { + + // Docs for patternTypes (i.e. `atoms.md`), don't have these rules and need them to pass below conditionals + if ( + !isset($patternStoreData['depth']) + && !isset($patternStoreData['hidden']) + && !isset($patternStoreData['noviewall']) + ) { + $patternStoreData["hidden"] = false; + $patternStoreData["noviewall"] = false; + $patternStoreData["depth"] = 0; + } + $canShow = isset($patternStoreData["hidden"]) && (!$patternStoreData["hidden"]) && (!$patternStoreData["noviewall"]); + + if (($patternStoreData["category"] == "pattern") && $canShow && ($patternStoreData["depth"] > 1) && (!in_array($patternStoreData["type"],$this->styleGuideExcludes))) { if ((($patternStoreData["type"] == $type) && empty($subtype)) || (empty($type) && empty($subtype)) || (($patternStoreData["type"] == $type) && ($patternStoreData["subtype"] == $subtype))) { @@ -101,8 +113,31 @@ public function run($type = "", $subtype = "") { $patternPartials[] = $patternPartialData; } - - } + + } else if ( + ($patternStoreData["category"] == "pattern") + && $canShow + && (isset($patternStoreData["full"]) + && ($type === $patternStoreData["full"] || $type === "")) + && ($subtype === "") + ) { + // This is for `patternType` docs. Given this structure: + // - _patterns/ + // - atoms/ + // - forms/ + // - atoms.md + // This will take the contents of `atoms.md` and place at top of "Atoms > View All" + + $patternPartialData = array(); + // Getting the name from md's `title: My Name` works here, as does the link, but it doesn't make sense to link to the view you are already on. Plus you can just do the title in the MD doc. Keeping here for now in case it's wanted later. + // $patternPartialData["patternName"] = isset($patternStoreData["nameClean"]) ? $patternStoreData["nameClean"] : ''; + // $patternPartialData["patternLink"] = $patternStoreData["full"] . "/index.html"; + + $patternPartialData["patternSectionSubtype"] = true; + $patternPartialData["patternDesc"] = isset($patternStoreData["desc"]) ? $patternStoreData["desc"] : ""; + + $patternPartials[] = $patternPartialData; + } } diff --git a/src/PatternLab/PatternData/Helpers/LineageHelper.php b/src/PatternLab/PatternData/Helpers/LineageHelper.php index 61185d65..a96c9db1 100644 --- a/src/PatternLab/PatternData/Helpers/LineageHelper.php +++ b/src/PatternLab/PatternData/Helpers/LineageHelper.php @@ -53,6 +53,51 @@ public function run() { foreach ($foundLineages as $lineage) { + /** + * Fix for Pattern Lab Lineages when using Twig Namespaces. + * Converts the full file path to PL-friendly shorthand so + * they are internally registered. + * + * 1. Only handle instances where we aren't or can't use the + * shorthand PL path reference in templates, specifically + * in Twig / D8 when we need to use Twig namespaces in + * our template paths. + * 2. Strip off the @ sign at the beginning of our $lineage string. + * 3. Break apart the full lineage path based on any slashes that + * may exist. + * 4. Store the length of our broken up path for reference below + * 5. Store the first part of the string up to the first slash "/" + * 6. Now grab the last part of the pattern key, based on the length + * of the path we previously exploded. + * 7. Remove any "_" from pattern Name. + * 8. Remove any potential prefixed numbers or number + dash + * combos on our Pattern Name. + * 9. Strip off the pattern path extension (.twig, + * .mustache, etc) if it exists. + * 10. If the pattern name parsed had an extension, + * re-assign our Pattern Name to that. + * 11. Finally, re-assign $lineage to the default PL pattern key. + */ + + if ($lineage[0] == '@') { /* [1] */ + $lineage = ltrim($lineage, '@'); /* [2] */ + $lineageParts = explode('/', $lineage); /* [3] */ + $length = count($lineageParts); /* [4] */ + $patternType = $lineageParts[0]; /* [5] */ + + $patternName = $lineageParts[$length - 1]; /* [6] */ + $patternName = ltrim($patternName, '_'); /* [7] */ + $patternName = preg_replace('/^[0-9\-]+/', '', + $patternName); /* [8] */ + + $patternNameStripped = explode('.' . $patternExtension, $patternName); /* [9] */ + + if (count($patternNameStripped) > 1) { /* [10] */ + $patternName = $patternNameStripped[0]; + } + $lineage = $patternType . "-" . $patternName; /* [11] */ + } + if (PatternData::getOption($lineage)) { $patternLineages[] = array("lineagePattern" => $lineage, @@ -62,7 +107,8 @@ public function run() { if (strpos($lineage, '/') === false) { $fileName = $patternStoreData["pathName"].".".$patternExtension; - Console::writeWarning("you may have a typo in ".$fileName.". `".$lineage."` is not a valid pattern..."); + // This doesn't work very consistently. @todo Improve error reporting when trying to include a Twig file that doesn't exist (b/c doing so simply outputs the path to the file you were trying to include, giving no error to user that include path had a typo) + // Console::writeWarning("you may have a typo in ".$fileName.". `".$lineage."` is not a valid pattern..."); } } diff --git a/src/PatternLab/PatternData/Helpers/PatternStateHelper.php b/src/PatternLab/PatternData/Helpers/PatternStateHelper.php index e8fd2b5c..817b61c0 100644 --- a/src/PatternLab/PatternData/Helpers/PatternStateHelper.php +++ b/src/PatternLab/PatternData/Helpers/PatternStateHelper.php @@ -17,6 +17,10 @@ use \PatternLab\PatternData; use \PatternLab\Timer; +/** + * Class PatternStateHelper + * @package PatternLab\PatternData\Helpers + */ class PatternStateHelper extends \PatternLab\PatternData\Helper { public function __construct($options = array()) { diff --git a/src/PatternLab/PatternData/Rule.php b/src/PatternLab/PatternData/Rule.php index a7c3ab25..bbb500b4 100644 --- a/src/PatternLab/PatternData/Rule.php +++ b/src/PatternLab/PatternData/Rule.php @@ -104,6 +104,9 @@ protected function compareProp($name, $propCompare, $exact = false) { protected function getPatternName($pattern, $clean = true) { $patternBits = explode("-",$pattern,2); $patternName = (((int)$patternBits[0] != 0) || ($patternBits[0] == '00')) ? $patternBits[1] : $pattern; + // replace possible dots with dashes. pattern names cannot contain dots + // since they are used as id/class names in the styleguidekit. + $patternName = str_replace('.', '-', $patternName); return ($clean) ? (str_replace("-"," ",$patternName)) : $patternName; } diff --git a/src/PatternLab/PatternData/Rules/DocumentationRule.php b/src/PatternLab/PatternData/Rules/DocumentationRule.php index 4e9ef3fa..528925fb 100644 --- a/src/PatternLab/PatternData/Rules/DocumentationRule.php +++ b/src/PatternLab/PatternData/Rules/DocumentationRule.php @@ -80,10 +80,26 @@ public function run($depth, $ext, $path, $pathName, $name) { "meta" => $yaml, "full" => $doc); + // can set `title: My Cool Pattern` instead of lifting from file name if (isset($title)) { $patternStoreData["nameClean"] = $title; } - + + $availableKeys = [ + 'state', // can use `state: inprogress` instead of `button@inprogress.mustache` + 'hidden', // setting to `true`, removes from menu and viewall, which is same as adding `_` prefix + 'noviewall', // setting to `true`, removes from view alls but keeps in menu, which is same as adding `-` prefix + 'order', // @todo implement order + 'tags', // not implemented, awaiting spec approval and integration with styleguide kit. adding to be in sync with Node version. + 'links', // not implemented, awaiting spec approval and integration with styleguide kit. adding to be in sync with Node version. + ]; + + foreach ($availableKeys as $key) { + if (isset($yaml[$key])) { + $patternStoreData[$key] = $yaml[$key]; + } + } + // if the pattern data store already exists make sure this data overwrites it $patternStoreData = (PatternData::checkOption($patternStoreKey)) ? array_replace_recursive(PatternData::getOption($patternStoreKey),$patternStoreData) : $patternStoreData; PatternData::setOption($patternStoreKey, $patternStoreData); diff --git a/src/PatternLab/PatternData/Rules/PseudoPatternRule.php b/src/PatternLab/PatternData/Rules/PseudoPatternRule.php index 426332e9..8575790c 100644 --- a/src/PatternLab/PatternData/Rules/PseudoPatternRule.php +++ b/src/PatternLab/PatternData/Rules/PseudoPatternRule.php @@ -171,7 +171,14 @@ public function run($depth, $ext, $path, $pathName, $name) { $patternStoreData["data"] = is_array($patternData) ? array_replace_recursive($patternDataBase, $patternData) : $patternDataBase; // if the pattern data store already exists make sure it is merged and overwrites this data - $patternStoreData = (PatternData::checkOption($patternStoreKey)) ? array_replace_recursive(PatternData::getOption($patternStoreKey),$patternStoreData) : $patternStoreData; + if (PatternData::checkOption($patternStoreKey)) { + $existingData = PatternData::getOption($patternStoreKey); + if (array_key_exists('nameClean', $existingData)) { + // don't overwrite nameClean + unset($patternStoreData['nameClean']); + } + $patternStoreData = array_replace_recursive($existingData, $patternStoreData); + } PatternData::setOption($patternStoreKey, $patternStoreData); }