hints = []; $this->setPluginsHints(); $this->setRenderingHints(); $this->setRulesHints(); $this->setTagsHints(); // Build the source. Note that Closure Compiler seems to require that each of HINT's // properties be declared as a const $js = "/** @const */ var HINT={};\n"; ksort($this->hints); foreach ($this->hints as $hintName => $hintValue) { $js .= '/** @const */ HINT.' . $hintName . '=' . json_encode($hintValue) . ";\n"; } return $js; } /** * Set the config on which hints are based * * @param array $config * @return void */ public function setConfig(array $config) { $this->config = $config; } /** * Set the collection of plugins * * @param PluginCollection $plugins * @return void */ public function setPlugins(PluginCollection $plugins) { $this->plugins = $plugins; } /** * Set the XSL on which hints are based * * @param string $xsl * @return void */ public function setXSL($xsl) { $this->xsl = $xsl; } /** * Set custom hints from plugins * * @return void */ protected function setPluginsHints() { foreach ($this->plugins as $plugin) { $this->hints += $plugin->getJSHints(); } $this->hints['regexp'] = 0; $this->hints['regexpLimit'] = 0; foreach ($this->config['plugins'] as $pluginConfig) { $this->hints['regexp'] |= isset($pluginConfig['regexp']); $this->hints['regexpLimit'] |= isset($pluginConfig['regexpLimit']); } } /** * Set hints related to rendering * * @return void */ protected function setRenderingHints() { // Test for post-processing in templates. Theorically allows for false positives and // false negatives, but not in any realistic setting $hints = [ 'hash' => 'data-s9e-livepreview-hash', 'ignoreAttrs' => 'data-s9e-livepreview-ignore-attrs', 'onRender' => 'data-s9e-livepreview-onrender', 'onUpdate' => 'data-s9e-livepreview-onupdate' ]; foreach ($hints as $hintName => $match) { $this->hints[$hintName] = (int) (strpos($this->xsl, $match) !== false); } } /** * Set hints related to rules * * @return void */ protected function setRulesHints() { $this->hints['closeAncestor'] = 0; $this->hints['closeParent'] = 0; $this->hints['createChild'] = 0; $this->hints['fosterParent'] = 0; $this->hints['requireAncestor'] = 0; $flags = 0; foreach ($this->config['tags'] as $tagConfig) { // Test which rules are in use foreach (array_intersect_key($tagConfig['rules'], $this->hints) as $k => $v) { $this->hints[$k] = 1; } $flags |= $tagConfig['rules']['flags']; } $flags |= $this->config['rootContext']['flags']; // Iterate over Parser::RULE_* constants and test which flags are set $parser = new ReflectionClass('s9e\\TextFormatter\\Parser'); foreach ($parser->getConstants() as $constName => $constValue) { if (substr($constName, 0, 5) === 'RULE_') { // This will set HINT.RULE_AUTO_CLOSE and others $this->hints[$constName] = ($flags & $constValue) ? 1 : 0; } } } /** * Set hints based on given tag's attributes config * * @param array $tagConfig * @return void */ protected function setTagAttributesHints(array $tagConfig) { if (empty($tagConfig['attributes'])) { return; } foreach ($tagConfig['attributes'] as $attrConfig) { $this->hints['attributeDefaultValue'] |= isset($attrConfig['defaultValue']); } } /** * Set hints related to tags config * * @return void */ protected function setTagsHints() { $this->hints['attributeDefaultValue'] = 0; $this->hints['namespaces'] = 0; foreach ($this->config['tags'] as $tagName => $tagConfig) { $this->hints['namespaces'] |= (strpos($tagName, ':') !== false); $this->setTagAttributesHints($tagConfig); } } }