public function run()
 {
     // set-up required vars
     $options = array();
     $options["exportFiles"] = true;
     $options["exportClean"] = Console::findCommandOption("clean");
     $options["moveStatic"] = false;
     FileUtil::cleanExport();
     $g = new Generator();
     $g->generate($options);
     FileUtil::exportStatic();
 }
 /**
  * Common init sequence
  */
 protected static function init()
 {
     // start the timer
     Timer::start();
     // initialize the console to print out any issues
     Console::init();
     // initialize the config for the pluginDir
     $baseDir = __DIR__ . "/../../../../../";
     Config::init($baseDir, false);
     // make sure the source dir is set-up
     $sourceDir = Config::getOption("sourceDir");
     if (!is_dir($sourceDir)) {
         FileUtil::makeDir($sourceDir);
     }
     // make sure the public dir is set-up
     $publicDir = Config::getOption("publicDir");
     if (!is_dir($publicDir)) {
         FileUtil::makeDir($publicDir);
     }
     Dispatcher::init();
 }
 /**
  * Move static files from source/ to public/
  */
 protected function moveStatic()
 {
     // set-up the dispatcher
     $dispatcherInstance = Dispatcher::getInstance();
     // note the start of the operation
     $dispatcherInstance->dispatch("generator.moveStaticStart");
     // common values
     $publicDir = Config::getOption("publicDir");
     $sourceDir = Config::getOption("sourceDir");
     $ignoreExt = Config::getOption("ie");
     $ignoreDir = Config::getOption("id");
     // iterate over all of the other files in the source directory
     $objects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($sourceDir), \RecursiveIteratorIterator::SELF_FIRST);
     // make sure dots are skipped
     $objects->setFlags(\FilesystemIterator::SKIP_DOTS);
     foreach ($objects as $name => $object) {
         // clean-up the file name and make sure it's not one of the pattern lab files or to be ignored
         $fileName = str_replace($sourceDir . DIRECTORY_SEPARATOR, "", $name);
         if ($fileName[0] != "_" && !in_array($object->getExtension(), $ignoreExt) && !in_array($object->getFilename(), $ignoreDir)) {
             // catch directories that have the ignored dir in their path
             $ignored = FileUtil::ignoreDir($fileName);
             // check to see if it's a new directory
             if (!$ignored && $object->isDir() && !is_dir($publicDir . "/" . $fileName)) {
                 mkdir($publicDir . "/" . $fileName);
             }
             // check to see if it's a new file or a file that has changed
             if (!$ignored && $object->isFile() && !file_exists($publicDir . "/" . $fileName)) {
                 FileUtil::moveStaticFile($fileName);
             }
         }
     }
     // note the end of the operation
     $dispatcherInstance->dispatch("generator.moveStaticEnd");
 }
示例#4
0
 /**
  * Adds the config options to a var to be accessed from the rest of the system
  * If it's an old config or no config exists this will update and generate it.
  * @param  {Boolean}       whether we should print out the status of the config being loaded
  */
 public static function init($baseDir = "", $verbose = true)
 {
     // make sure a base dir was supplied
     if (empty($baseDir)) {
         Console::writeError("need a base directory to initialize the config class...");
     }
     // normalize the baseDir
     $baseDir = FileUtil::normalizePath($baseDir);
     // double-check the default config file exists
     if (!is_dir($baseDir)) {
         Console::writeError("make sure " . $baseDir . " exists...");
     }
     // set the baseDir option
     self::$options["baseDir"] = $baseDir[strlen($baseDir) - 1] == DIRECTORY_SEPARATOR ? $baseDir : $baseDir . DIRECTORY_SEPARATOR;
     // can't add __DIR__ above so adding here
     if (!self::$dirAdded) {
         // set-up the paths
         self::$userConfigDirClean = self::$options["baseDir"] . self::$userConfigDirClean;
         self::$userConfigDirDash = self::$options["baseDir"] . self::$userConfigDirDash;
         self::$userConfigDir = is_dir(self::$userConfigDirDash) ? self::$userConfigDirDash : self::$userConfigDirClean;
         self::$userConfigPath = self::$userConfigDir . DIRECTORY_SEPARATOR . self::$userConfig;
         self::$plConfigPath = self::$options["baseDir"] . "vendor/pattern-lab/core/" . self::$plConfigPath;
         self::$dirAdded = true;
         // just in case the config directory doesn't exist at all
         if (!is_dir(self::$userConfigDir)) {
             mkdir(self::$userConfigDir);
         }
     }
     // make sure migrate doesn't happen by default
     $migrate = false;
     $diffVersion = false;
     // double-check the default config file exists
     if (!file_exists(self::$plConfigPath)) {
         Console::writeError("make sure <path>" . self::$plConfigPath . "</path> exists before trying to have Pattern Lab build the config.yml file automagically...");
     }
     // set the default config using the pattern lab config
     try {
         $data = Yaml::parse(file_get_contents(self::$plConfigPath));
     } catch (ParseException $e) {
         Console::writeError("Config parse error in <path>" . self::$plConfigPath . "</path>: " . $e->getMessage());
     }
     // load the options from the default file
     self::loadOptions($data);
     // make sure these are copied
     $defaultOptions = self::$options;
     // check to see if the user config exists, if not create it
     if ($verbose) {
         Console::writeLine("configuring pattern lab...");
     }
     if (!file_exists(self::$userConfigPath)) {
         $migrate = true;
     } else {
         try {
             $data = Yaml::parse(file_get_contents(self::$userConfigPath));
         } catch (ParseException $e) {
             Console::writeError("Config parse error in <path>" . self::$userConfigPath . "</path>: " . $e->getMessage());
         }
         self::loadOptions($data);
     }
     // compare version numbers
     $diffVersion = self::$options["v"] != $defaultOptions["v"] ? true : false;
     // run an upgrade and migrations if necessary
     if ($migrate || $diffVersion) {
         if ($verbose) {
             Console::writeInfo("upgrading your version of pattern lab...");
         }
         if ($migrate) {
             if (!@copy(self::$plConfigPath, self::$userConfigPath)) {
                 Console::writeError("make sure that Pattern Lab can write a new config to " . self::$userConfigPath . "...");
                 exit;
             }
         } else {
             self::$options = self::writeNewConfigFile(self::$options, $defaultOptions);
         }
     }
     // making sure the config isn't empty
     if (empty(self::$options) && $verbose) {
         Console::writeError("a set of configuration options is required to use Pattern Lab...");
         exit;
     }
     // set-up the various dirs
     self::$options["coreDir"] = is_dir(self::$options["baseDir"] . "_core") ? self::$options["baseDir"] . "_core" : self::$options["baseDir"] . "core";
     self::$options["exportDir"] = isset(self::$options["exportDir"]) ? self::$options["baseDir"] . self::cleanDir(self::$options["exportDir"]) : self::$options["baseDir"] . "exports";
     self::$options["packagesDir"] = isset(self::$options["packagesDir"]) ? self::$options["baseDir"] . self::cleanDir(self::$options["packagesDir"]) : self::$options["baseDir"] . "packages";
     self::$options["publicDir"] = isset(self::$options["publicDir"]) ? self::$options["baseDir"] . self::cleanDir(self::$options["publicDir"]) : self::$options["baseDir"] . "public";
     self::$options["scriptsDir"] = isset(self::$options["scriptsDir"]) ? self::$options["baseDir"] . self::cleanDir(self::$options["scriptsDir"]) : self::$options["baseDir"] . "scripts";
     self::$options["sourceDir"] = isset(self::$options["sourceDir"]) ? self::$options["baseDir"] . self::cleanDir(self::$options["sourceDir"]) : self::$options["baseDir"] . "source";
     self::$options["componentDir"] = self::$options["publicDir"] . "/patternlab-components";
     self::$options["dataDir"] = self::$options["sourceDir"] . "/_data";
     self::$options["patternExportDir"] = self::$options["exportDir"] . "/patterns";
     self::$options["patternPublicDir"] = self::$options["publicDir"] . "/patterns";
     self::$options["patternSourceDir"] = self::$options["sourceDir"] . "/_patterns";
     // make sure styleguideExcludes is set to an array even if it's empty
     if (is_string(self::$options["styleGuideExcludes"])) {
         self::$options["styleGuideExcludes"] = array();
     }
     // set the cacheBuster
     self::$options["cacheBuster"] = self::$options["cacheBusterOn"] == "false" ? 0 : time();
     // provide the default for enable CSS. performance hog so it should be run infrequently
     self::$options["enableCSS"] = false;
     // which of these should be exposed in the front-end?
     self::$options["exposedOptions"] = array();
     self::setExposedOption("cacheBuster");
     self::setExposedOption("ishFontSize");
     self::setExposedOption("ishMaximum");
     self::setExposedOption("ishMinimum");
 }
示例#5
0
 /**
  * Watch the source/ directory for any changes to existing files. Will run forever if given the chance.
  * @param  {Boolean}       decide if the reload server should be turned on
  * @param  {Boolean}       decide if static files like CSS and JS should be moved
  */
 public function watch($options = array())
 {
     // double-checks options was properly set
     if (empty($options)) {
         Console::writeError("need to pass options to generate...");
     }
     // set default attributes
     $moveStatic = isset($options["moveStatic"]) ? $options["moveStatic"] : true;
     $noCacheBuster = isset($options["noCacheBuster"]) ? $options["noCacheBuster"] : false;
     // make sure a copy of the given options are saved for using when running generate
     $this->options = $options;
     // set-up the Dispatcher
     $dispatcherInstance = Dispatcher::getInstance();
     $dispatcherInstance->dispatch("watcher.start");
     if ($noCacheBuster) {
         Config::setOption("cacheBuster", 0);
     }
     $c = false;
     // track that one loop through the pattern file listing has completed
     $o = new \stdClass();
     // create an object to hold the properties
     $cp = new \stdClass();
     // create an object to hold a clone of $o
     $o->patterns = new \stdClass();
     Console::writeLine("watching your site for changes...");
     // default vars
     $publicDir = Config::getOption("publicDir");
     $sourceDir = Config::getOption("sourceDir");
     $patternSourceDir = Config::getOption("patternSourceDir");
     $ignoreExts = Config::getOption("ie");
     $ignoreDirs = Config::getOption("id");
     $patternExt = Config::getOption("patternExtension");
     // build the file extensions based on the rules
     $fileExtensions = array();
     $patternRules = PatternData::getRules();
     foreach ($patternRules as $patternRule) {
         $extensions = $patternRule->getProp("extProp");
         if (strpos($extensions, "&&") !== false) {
             $extensions = explode("&&", $extensions);
         } else {
             if (strpos($extensions, "||") !== false) {
                 $extensions = explode("||", $extensions);
             } else {
                 $extensions = array($extensions);
             }
         }
         foreach ($extensions as $extension) {
             if (!in_array($extension, $fileExtensions)) {
                 $fileExtensions[] = $extension;
             }
         }
     }
     // run forever
     while (true) {
         // clone the patterns so they can be checked in case something gets deleted
         $cp = clone $o->patterns;
         // iterate over the patterns & related data and regenerate the entire site if they've changed
         $patternObjects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($patternSourceDir), \RecursiveIteratorIterator::SELF_FIRST);
         // make sure dots are skipped
         $patternObjects->setFlags(\FilesystemIterator::SKIP_DOTS);
         foreach ($patternObjects as $name => $object) {
             // clean-up the file name and make sure it's not one of the pattern lab files or to be ignored
             $fileName = str_replace($patternSourceDir . DIRECTORY_SEPARATOR, "", $name);
             $fileNameClean = str_replace(DIRECTORY_SEPARATOR . "_", DIRECTORY_SEPARATOR, $fileName);
             if ($object->isFile() && in_array($object->getExtension(), $fileExtensions)) {
                 // make sure this isn't a hidden pattern
                 $patternParts = explode(DIRECTORY_SEPARATOR, $fileName);
                 $pattern = isset($patternParts[2]) ? $patternParts[2] : $patternParts[1];
                 // make sure the pattern still exists in source just in case it's been deleted during the iteration
                 if (file_exists($name)) {
                     $mt = $object->getMTime();
                     if (isset($o->patterns->{$fileName}) && $o->patterns->{$fileName} != $mt) {
                         $o->patterns->{$fileName} = $mt;
                         $this->updateSite($fileName, "changed");
                     } else {
                         if (!isset($o->patterns->{$fileName}) && $c) {
                             $o->patterns->{$fileName} = $mt;
                             $this->updateSite($fileName, "added");
                             if ($object->getExtension() == $patternExt) {
                                 $patternSrcPath = str_replace("." . $patternExt, "", $fileName);
                                 $patternDestPath = str_replace("/", "-", $patternSrcPath);
                                 $render = $pattern[0] != "_" ? true : false;
                                 $this->patternPaths[$patternParts[0]][$pattern] = array("patternSrcPath" => $patternSrcPath, "patternDestPath" => $patternDestPath, "render" => $render);
                             }
                         } else {
                             if (!isset($o->patterns->{$fileName})) {
                                 $o->patterns->{$fileName} = $mt;
                             }
                         }
                     }
                     if ($c && isset($o->patterns->{$fileName})) {
                         unset($cp->{$fileName});
                     }
                 } else {
                     // the file was removed during the iteration so remove references to the item
                     unset($o->patterns->{$fileName});
                     unset($cp->{$fileName});
                     unset($this->patternPaths[$patternParts[0]][$pattern]);
                     $this->updateSite($fileName, "removed");
                 }
             }
         }
         // make sure old entries are deleted
         // will throw "pattern not found" errors if an entire directory is removed at once but that shouldn't be a big deal
         if ($c) {
             foreach ($cp as $fileName => $mt) {
                 unset($o->patterns->{$fileName});
                 $patternParts = explode(DIRECTORY_SEPARATOR, $fileName);
                 $pattern = isset($patternParts[2]) ? $patternParts[2] : $patternParts[1];
                 unset($this->patternPaths[$patternParts[0]][$pattern]);
                 $this->updateSite($fileName, "removed");
             }
         }
         // iterate over annotations, data, meta and any other _ dirs
         $watchDirs = glob($sourceDir . DIRECTORY_SEPARATOR . "_*", GLOB_ONLYDIR);
         foreach ($watchDirs as $watchDir) {
             if ($watchDir != $patternSourceDir) {
                 // iterate over the data files and regenerate the entire site if they've changed
                 $objects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($watchDir), \RecursiveIteratorIterator::SELF_FIRST);
                 // make sure dots are skipped
                 $objects->setFlags(\FilesystemIterator::SKIP_DOTS);
                 foreach ($objects as $name => $object) {
                     $fileName = str_replace($sourceDir . DIRECTORY_SEPARATOR, "", $name);
                     $mt = $object->getMTime();
                     if (!isset($o->{$fileName})) {
                         $o->{$fileName} = $mt;
                         if ($c) {
                             $this->updateSite($fileName, "added");
                         }
                     } else {
                         if ($o->{$fileName} != $mt) {
                             $o->{$fileName} = $mt;
                             if ($c) {
                                 $this->updateSite($fileName, "changed");
                             }
                         }
                     }
                 }
             }
         }
         // iterate over all of the other files in the source directory and move them if their modified time has changed
         if ($moveStatic) {
             $objects = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($sourceDir . DIRECTORY_SEPARATOR), \RecursiveIteratorIterator::SELF_FIRST);
             // make sure dots are skipped
             $objects->setFlags(\FilesystemIterator::SKIP_DOTS);
             foreach ($objects as $name => $object) {
                 // clean-up the file name and make sure it's not one of the pattern lab files or to be ignored
                 $fileName = str_replace($sourceDir . DIRECTORY_SEPARATOR, "", $name);
                 if ($fileName[0] != "_" && !in_array($object->getExtension(), $ignoreExts) && !in_array($object->getFilename(), $ignoreDirs)) {
                     // catch directories that have the ignored dir in their path
                     $ignoreDir = FileUtil::ignoreDir($fileName);
                     // check to see if it's a new directory
                     if (!$ignoreDir && $object->isDir() && !isset($o->{$fileName}) && !is_dir($publicDir . "/" . $fileName)) {
                         mkdir($publicDir . "/" . $fileName);
                         $o->{$fileName} = "dir created";
                         // placeholder
                         Console::writeLine($fileName . "/ directory was created...");
                     }
                     // check to see if it's a new file or a file that has changed
                     if (file_exists($name)) {
                         $mt = $object->getMTime();
                         if (!$ignoreDir && $object->isFile() && !isset($o->{$fileName}) && !file_exists($publicDir . "/" . $fileName)) {
                             $o->{$fileName} = $mt;
                             FileUtil::moveStaticFile($fileName, "added");
                             if ($object->getExtension() == "css") {
                                 $this->updateSite($fileName, "changed", 0);
                                 // make sure the site is updated for MQ reasons
                             }
                         } else {
                             if (!$ignoreDir && $object->isFile() && isset($o->{$fileName}) && $o->{$fileName} != $mt) {
                                 $o->{$fileName} = $mt;
                                 FileUtil::moveStaticFile($fileName, "changed");
                                 if ($object->getExtension() == "css") {
                                     $this->updateSite($fileName, "changed", 0);
                                     // make sure the site is updated for MQ reasons
                                 }
                             } else {
                                 if (!isset($o->fileName)) {
                                     $o->{$fileName} = $mt;
                                 }
                             }
                         }
                     } else {
                         unset($o->{$fileName});
                     }
                 }
             }
         }
         $c = true;
         // taking out the garbage. basically killing mustache after each run.
         if (gc_enabled()) {
             gc_collect_cycles();
         }
         // pause for .05 seconds to give the CPU a rest
         usleep(50000);
     }
 }
示例#6
0
 /**
  * Generates the data that powers the index page
  */
 protected function generateIndex()
 {
     // bomb if missing index.html
     if (!file_exists(Config::getOption("publicDir") . "/index.html")) {
         $index = Console::getHumanReadablePath(Config::getOption("publicDir")) . DIRECTORY_SEPARATOR . "index.html";
         Console::writeError("<path>" . $index . "</path> is missing. grab a copy from your StyleguideKit...");
     }
     // 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");
     foreach ($exposedOptions as $exposedOption) {
         $config[$exposedOption] = Config::getOption($exposedOption);
     }
     $output .= "var config = " . json_encode($config) . ";\n";
     // load the ish Controls
     $ishControls = array();
     $controlsToHide = array();
     $ishControlsHide = Config::getOption("ishControlsHide");
     if ($ishControlsHide) {
         foreach ($ishControlsHide as $controlToHide) {
             $controlsToHide[$controlToHide] = "true";
         }
     }
     $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");
     if (!is_dir($componentDir)) {
         mkdir($componentDir);
     }
     $componentPackagesDir = $componentDir . "/packages";
     if (!is_dir($componentDir . "/packages")) {
         mkdir($componentDir . "/packages");
     }
     $finder = new Finder();
     $finder->files()->name("*.json")->in($componentPackagesDir);
     $finder->sortByName();
     foreach ($finder as $file) {
         $filename = $file->getFilename();
         if ($filename[0] != "_") {
             $javascriptPaths = array();
             $packageInfo = json_decode(file_get_contents($file->getPathname()), true);
             foreach ($packageInfo["templates"] as $templateKey => $templatePath) {
                 $templatePathFull = $componentDir . "/" . $packageInfo["name"] . "/" . $templatePath;
                 $packageInfo["templates"][$templateKey] = file_exists($templatePathFull) ? file_get_contents($templatePathFull) : "";
             }
             foreach ($packageInfo["javascripts"] as $key => $javascriptPath) {
                 $javascriptPaths[] = "patternlab-components/" . $packageInfo["name"] . "/" . $javascriptPath;
             }
             $packageInfo["javascripts"] = $javascriptPaths;
             $packagesInfo[] = $packageInfo;
         }
     }
     $output .= "var plugins = " . json_encode($packagesInfo) . ";";
     // write out the data
     file_put_contents($dataDir . "/patternlab-data.js", $output);
     // note the end of the operation
     $dispatcherInstance->dispatch("builder.generateIndexEnd");
 }
示例#7
0
 /**
  * Adds the config options to a var to be accessed from the rest of the system
  * If it's an old config or no config exists this will update and generate it.
  * @param  {Boolean}       whether we should print out the status of the config being loaded
  */
 public static function init($baseDir = "", $verbose = true)
 {
     // make sure a base dir was supplied
     if (empty($baseDir)) {
         Console::writeError("need a base directory to initialize the config class...");
     }
     // normalize the baseDir
     $baseDir = FileUtil::normalizePath($baseDir);
     // double-check the default config file exists
     if (!is_dir($baseDir)) {
         Console::writeError("make sure " . $baseDir . " exists...");
     }
     // set the baseDir option
     self::$options["baseDir"] = $baseDir[strlen($baseDir) - 1] == DIRECTORY_SEPARATOR ? $baseDir : $baseDir . DIRECTORY_SEPARATOR;
     // set-up the paths
     self::$userConfigDirClean = self::$options["baseDir"] . self::$userConfigDirClean;
     self::$userConfigDirDash = self::$options["baseDir"] . self::$userConfigDirDash;
     self::$userConfigDir = is_dir(self::$userConfigDirDash) ? self::$userConfigDirDash : self::$userConfigDirClean;
     self::$userConfigPath = self::$userConfigDir . DIRECTORY_SEPARATOR . self::$userConfig;
     self::$plConfigPath = self::$options["baseDir"] . "vendor/pattern-lab/core/" . self::$plConfigPath;
     // can't add __DIR__ above so adding here
     if (!is_dir(self::$userConfigDir)) {
         mkdir(self::$userConfigDir);
     }
     // check to see if the user config exists, if not create it
     if ($verbose) {
         Console::writeLine("configuring pattern lab...");
     }
     // make sure migrate doesn't happen by default
     $migrate = false;
     $diffVersion = false;
     $defaultOptions = array();
     $userOptions = array();
     // double-check the default config file exists
     if (!file_exists(self::$plConfigPath)) {
         Console::writeError("the default options for Pattern Lab don't seem to exist at <path>" . Console::getHumanReadablePath(self::$plConfigPath) . "</path>. please check on the install location of pattern lab...");
     }
     // set the default config using the pattern lab config
     try {
         $defaultOptions = Yaml::parse(file_get_contents(self::$plConfigPath));
         self::$options = array_merge(self::$options, $defaultOptions);
     } catch (ParseException $e) {
         Console::writeError("Config parse error in <path>" . Console::getHumanReadablePath(self::$plConfigPath) . "</path>: " . $e->getMessage());
     }
     // double-check the user's config exists. if not mark that we should migrate the default one
     if (file_exists(self::$userConfigPath)) {
         try {
             $userOptions = Yaml::parse(file_get_contents(self::$userConfigPath));
             self::$options = array_merge(self::$options, $userOptions);
         } catch (ParseException $e) {
             Console::writeError("Config parse error in <path>" . Console::getHumanReadablePath(self::$userConfigPath) . "</path>: " . $e->getMessage());
         }
     } else {
         $migrate = true;
     }
     // compare version numbers
     $diffVersion = isset($userOptions["v"]) && $userOptions["v"] == $defaultOptions["v"] ? false : true;
     // run an upgrade and migrations if necessary
     if ($migrate || $diffVersion) {
         if ($verbose) {
             Console::writeInfo("upgrading your version of pattern lab...");
         }
         if ($migrate) {
             if (!@copy(self::$plConfigPath, self::$userConfigPath)) {
                 Console::writeError("make sure that Pattern Lab can write a new config to " . self::$userConfigPath . "...");
                 exit;
             }
         } else {
             self::$options = self::writeNewConfigFile(self::$options, $defaultOptions);
         }
     }
     // making sure the config isn't empty
     if (empty(self::$options) && $verbose) {
         Console::writeError("a set of configuration options is required to use Pattern Lab...");
         exit;
     }
     // set-up the various dirs
     self::$options["configDir"] = self::$userConfigDir;
     self::$options["configPath"] = self::$userConfigPath;
     self::$options["coreDir"] = is_dir(self::$options["baseDir"] . "_core") ? self::$options["baseDir"] . "_core" : self::$options["baseDir"] . "core";
     self::$options["exportDir"] = isset(self::$options["exportDir"]) ? self::$options["baseDir"] . self::cleanDir(self::$options["exportDir"]) : self::$options["baseDir"] . "exports";
     self::$options["publicDir"] = isset(self::$options["publicDir"]) ? self::$options["baseDir"] . self::cleanDir(self::$options["publicDir"]) : self::$options["baseDir"] . "public";
     self::$options["scriptsDir"] = isset(self::$options["scriptsDir"]) ? self::$options["baseDir"] . self::cleanDir(self::$options["scriptsDir"]) : self::$options["baseDir"] . "scripts";
     self::$options["sourceDir"] = isset(self::$options["sourceDir"]) ? self::$options["baseDir"] . self::cleanDir(self::$options["sourceDir"]) : self::$options["baseDir"] . "source";
     self::$options["componentDir"] = isset(self::$options["componentDir"]) ? self::$options["publicDir"] . DIRECTORY_SEPARATOR . self::cleanDir(self::$options["componentDir"]) : self::$options["publicDir"] . DIRECTORY_SEPARATOR . "patternlab-components";
     self::$options["dataDir"] = isset(self::$options["dataDir"]) ? self::$options["sourceDir"] . DIRECTORY_SEPARATOR . self::cleanDir(self::$options["dataDir"]) : self::$options["sourceDir"] . DIRECTORY_SEPARATOR . "_data";
     self::$options["patternExportDir"] = isset(self::$options["patternExportDir"]) ? self::$options["exportDir"] . DIRECTORY_SEPARATOR . self::cleanDir(self::$options["patternExportDir"]) : self::$options["exportDir"] . DIRECTORY_SEPARATOR . "patterns";
     self::$options["patternPublicDir"] = isset(self::$options["patternPublicDir"]) ? self::$options["publicDir"] . DIRECTORY_SEPARATOR . self::cleanDir(self::$options["patternPublicDir"]) : self::$options["publicDir"] . DIRECTORY_SEPARATOR . "patterns";
     self::$options["patternSourceDir"] = isset(self::$options["patternSourceDir"]) ? self::$options["sourceDir"] . DIRECTORY_SEPARATOR . self::cleanDir(self::$options["patternSourceDir"]) : self::$options["sourceDir"] . DIRECTORY_SEPARATOR . "_patterns";
     self::$options["metaDir"] = isset(self::$options["metaDir"]) ? self::$options["sourceDir"] . DIRECTORY_SEPARATOR . self::cleanDir(self::$options["metaDir"]) : self::$options["sourceDir"] . DIRECTORY_SEPARATOR . "_meta/";
     self::$options["annotationsDir"] = isset(self::$options["annotationsDir"]) ? self::$options["sourceDir"] . DIRECTORY_SEPARATOR . self::cleanDir(self::$options["annotationsDir"]) : self::$options["sourceDir"] . DIRECTORY_SEPARATOR . "_annotations/";
     // set-up outputFileSuffixes
     self::$options["outputFileSuffixes"]["rendered"] = isset(self::$options["outputFileSuffixes"]["rendered"]) ? self::$options["outputFileSuffixes"]["rendered"] : '';
     self::$options["outputFileSuffixes"]["rawTemplate"] = isset(self::$options["outputFileSuffixes"]["rawTemplate"]) ? self::$options["outputFileSuffixes"]["rawTemplate"] : '';
     self::$options["outputFileSuffixes"]["markupOnly"] = isset(self::$options["outputFileSuffixes"]["markupOnly"]) ? self::$options["outputFileSuffixes"]["markupOnly"] : '.markup-only';
     // handle a pre-2.1.0 styleguideKitPath before saving it
     if (isset(self::$options["styleguideKitPath"])) {
         self::$options["styleguideKitPath"] = self::$options["baseDir"] . self::cleanDir(self::getStyleguideKitPath(self::$options["styleguideKitPath"]));
     }
     // double-check a few directories are real and set-up
     FileUtil::checkPathFromConfig(self::$options["sourceDir"], self::$userConfigPath, "sourceDir");
     FileUtil::checkPathFromConfig(self::$options["publicDir"], self::$userConfigPath, "publicDir");
     // make sure styleguideExcludes is set to an array even if it's empty
     if (is_string(self::$options["styleGuideExcludes"])) {
         self::$options["styleGuideExcludes"] = array();
     }
     // set the cacheBuster
     self::$options["cacheBuster"] = self::$options["cacheBusterOn"] == "false" ? 0 : time();
     // provide the default for enable CSS. performance hog so it should be run infrequently
     self::$options["enableCSS"] = false;
     // which of these should be exposed in the front-end?
     self::$options["exposedOptions"] = array();
     self::setExposedOption("cacheBuster");
     self::setExposedOption("defaultPattern");
     self::setExposedOption("defaultShowPatternInfo");
     self::setExposedOption("ishFontSize");
     self::setExposedOption("ishMaximum");
     self::setExposedOption("ishMinimum");
     self::setExposedOption("outputFileSuffixes");
     self::setExposedOption("plugins");
 }