public function filterConfig($target)
 {
     $value = $this->getArrayCopy();
     if ($target === 'JS') {
         $value = new Dictionary(ConfigHelper::filterConfig($value, $target));
     }
     return $value;
 }
 /**
  * @testdox asConfig() returns a list of [attrName, Regexp instance, map] arrays
  */
 public function testGetConfig()
 {
     $collection = new AttributePreprocessorCollection();
     $collection->add('x', '#(?<x1>x1)#');
     $collection->add('x', '#(?<x2>x2)#');
     $collection->add('y', '#(?<y1>y1)#');
     $collection->add('y', '#(?<y2>y2)#');
     $config = $collection->asConfig();
     ConfigHelper::filterVariants($config);
     $this->assertSame([['x', '#(?<x1>x1)#', ['', 'x1']], ['x', '#(?<x2>x2)#', ['', 'x2']], ['y', '#(?<y1>y1)#', ['', 'y1']], ['y', '#(?<y2>y2)#', ['', 'y2']]], $config);
 }
 public function assertHintsContain($str)
 {
     $config = $this->configurator->asConfig();
     ConfigHelper::filterVariants($config, 'JS');
     $xsl = $this->configurator->rendering->engine->getXSL($this->configurator->rendering);
     $generator = new HintGenerator();
     $generator->setConfig($config);
     $generator->setPlugins($this->configurator->plugins);
     $generator->setXSL($xsl);
     $this->assertContains($str, $generator->getHints());
 }
Beispiel #4
0
 /**
  * {@inheritdoc}
  */
 public function asConfig()
 {
     $config = ConfigHelper::toArray(get_object_vars($this));
     if (!$this->forceLookahead) {
         unset($config['forceLookahead']);
     }
     if (isset($config['predefinedAttributes'])) {
         $config['predefinedAttributes'] = new Dictionary($config['predefinedAttributes']);
     }
     return $config;
 }
Beispiel #5
0
 public function getParser(array $config = \null)
 {
     $this->configOptimizer->reset();
     $rendererGenerator = new XSLT();
     $this->xsl = $rendererGenerator->getXSL($this->configurator->rendering);
     $this->config = isset($config) ? $config : $this->configurator->asConfig();
     ConfigHelper::filterVariants($this->config, 'JS');
     $this->config = $this->callbackGenerator->replaceCallbacks($this->config);
     $src = $this->getHints() . $this->injectConfig($this->getSource());
     $src .= $this->getExports();
     $src = $this->getMinifier()->get($src);
     $src = '(function(){' . $src . '})()';
     return $src;
 }
 /**
  * @testdox Filters work
  * @dataProvider getData
  */
 public function testFilters($filter, $original, $expected, $logs = [], $setup = null)
 {
     $this->configurator->tags->add('FOO')->attributes->add('foo')->filterChain->append($filter);
     if (isset($setup)) {
         $setup($this->configurator);
     }
     $config = $this->configurator->asConfig();
     ConfigHelper::filterVariants($config);
     $logger = new Logger();
     $parser = new ReflectionClass('s9e\\TextFormatter\\Parser');
     $method = $parser->getMethod('executeFilter');
     $method->setAccessible(true);
     $actual = $method->invoke(null, $config['tags']['FOO']['attributes']['foo']['filterChain'][0], ['attrName' => 'foo', 'attrValue' => $original, 'logger' => $logger, 'registeredVars' => $config['registeredVars']]);
     $this->assertSame($expected, $actual);
     if ($logs instanceof Closure) {
         $logs = $logs();
     }
     $this->assertSame($logs, $logger->get(), "Logs don't match");
 }
 /**
  * @testdox asConfig() returns the regexps in a "generics" array where each element is in the form [<tagName>,<regexp>,<passthrough index>,<map>]
  */
 public function testAsConfig()
 {
     $plugin = $this->configurator->plugins->load('Preg');
     $plugin->replace('/(?<foo>[0-9]+)/', '');
     $plugin->replace('/(?<bar>[a-z]+)/', '');
     $config = $plugin->asConfig();
     ConfigHelper::filterVariants($config);
     $this->assertEquals(['generics' => [['PREG_C53BB427', '/(?<foo>[0-9]+)/', 0, ['', 'foo']], ['PREG_DCEA6E9C', '/(?<bar>[a-z]+)/', 0, ['', 'bar']]]], $config);
 }
 /**
  * @testdox executeAttributePreprocessors() returns TRUE even if no source attribute was present
  */
 public function testExecuteAttributePreprocessorsReturnsTrue()
 {
     $tagConfig = new TagConfig();
     $tagConfig->attributePreprocessors->add('foo', '/^(?<bar>[a-z])(?<baz>[a-z])$/i');
     $tagConfig = $tagConfig->asConfig();
     ConfigHelper::filterVariants($tagConfig);
     $tag = new Tag(Tag::SELF_CLOSING_TAG, 'X', 0, 0);
     $this->assertTrue(Parser::executeAttributePreprocessors($tag, $tagConfig));
 }
Beispiel #9
0
 public function asConfig()
 {
     if (!\count($this->collection)) {
         return;
     }
     $codes = \array_keys(\iterator_to_array($this->collection));
     $regexp = '/';
     if ($this->notAfter !== '') {
         $regexp .= '(?<!' . $this->notAfter . ')';
     }
     $regexp .= RegexpBuilder::fromList($codes);
     if ($this->notBefore !== '') {
         $regexp .= '(?!' . $this->notBefore . ')';
     }
     $regexp .= '/S';
     if (\preg_match('/\\\\[pP](?>\\{\\^?\\w+\\}|\\w\\w?)/', $regexp)) {
         $regexp .= 'u';
     }
     $regexp = \preg_replace('/(?<!\\\\)((?>\\\\\\\\)*)\\(\\?:/', '$1(?>', $regexp);
     $config = array('quickMatch' => $this->quickMatch, 'regexp' => $regexp, 'tagName' => $this->tagName);
     if ($this->notAfter !== '') {
         $lpos = 6 + \strlen($this->notAfter);
         $rpos = \strrpos($regexp, '/');
         $jsRegexp = RegexpConvertor::toJS('/' . \substr($regexp, $lpos, $rpos - $lpos) . '/', \true);
         $config['regexp'] = new Variant($regexp);
         $config['regexp']->set('JS', $jsRegexp);
         $config['notAfter'] = new Variant();
         $config['notAfter']->set('JS', RegexpConvertor::toJS('/' . $this->notAfter . '/'));
     }
     if ($this->quickMatch === \false) {
         $config['quickMatch'] = ConfigHelper::generateQuickMatchFromList($codes);
     }
     return $config;
 }
Beispiel #10
0
 /**
  * {@inheritdoc}
  */
 public function asConfig()
 {
     $vars = get_object_vars($this);
     // Remove properties that are not needed during parsing
     unset($vars['defaultChildRule']);
     unset($vars['defaultDescendantRule']);
     unset($vars['template']);
     // If there are no attribute preprocessors defined, we can remove the step from this tag's
     // filterChain
     if (!count($this->attributePreprocessors)) {
         $callback = 's9e\\TextFormatter\\Parser::executeAttributePreprocessors';
         // We operate on a copy of the filterChain, without modifying the original
         $filterChain = clone $vars['filterChain'];
         // Process the chain in reverse order so that we don't skip indices
         $i = count($filterChain);
         while (--$i >= 0) {
             if ($filterChain[$i]->getCallback() === $callback) {
                 unset($filterChain[$i]);
             }
         }
         $vars['filterChain'] = $filterChain;
     }
     return ConfigHelper::toArray($vars);
 }
Beispiel #11
0
 /**
  * {@inheritdoc}
  */
 public function getJSHints()
 {
     $quickMatch = ConfigHelper::generateQuickMatchFromList(array_keys($this->aliases));
     return ['EMOJI_HAS_ALIASES' => !empty($this->aliases), 'EMOJI_HAS_ALIAS_QUICKMATCH' => $quickMatch !== false];
 }
Beispiel #12
0
 /**
  * Return an instance of s9e\TextFormatter\Plugins\Censor\Helper
  *
  * @return Helper
  */
 public function getHelper()
 {
     $config = $this->asConfig();
     if (isset($config)) {
         ConfigHelper::filterVariants($config);
     } else {
         // Use a dummy config with a regexp that doesn't match anything
         $config = ['attrName' => $this->attrName, 'regexp' => '/(?!)/', 'tagName' => $this->tagName];
     }
     return new Helper($config);
 }
Beispiel #13
0
 /**
  * @return mixed
  */
 public function asConfig()
 {
     return ConfigHelper::toArray($this->items, true);
 }
Beispiel #14
0
 /**
  * {@inheritdoc}
  */
 public function asConfig()
 {
     $vars = get_object_vars($this);
     unset($vars['markedSafe']);
     return ConfigHelper::toArray($vars);
 }
Beispiel #15
0
 /**
  * Get a JavaScript parser
  *
  * @param  array  $config Config array returned by the configurator
  * @return string         JavaScript parser
  */
 public function getParser(array $config = null)
 {
     $this->configOptimizer->reset();
     // Get the stylesheet used for rendering
     $this->xsl = (new XSLT())->getXSL($this->configurator->rendering);
     // Prepare the parser's config
     $this->config = isset($config) ? $config : $this->configurator->asConfig();
     ConfigHelper::filterVariants($this->config, 'JS');
     $this->config = $this->callbackGenerator->replaceCallbacks($this->config);
     // Get the parser's source and inject its config
     $src = $this->getHints() . $this->injectConfig($this->getSource());
     // Export the public API
     $src .= $this->getExports();
     // Minify the source
     $src = $this->getMinifier()->get($src);
     // Wrap the source in a function to protect the global scope
     $src = '(function(){' . $src . '})()';
     return $src;
 }
 /**
  * {@inheritdoc}
  */
 public function asConfig()
 {
     $config = ['callback' => $this->callback];
     foreach ($this->params as $k => $v) {
         if (is_numeric($k)) {
             // By value
             $config['params'][] = $v;
         } elseif (isset($this->vars[$k])) {
             // By name, but the value is readily available in $this->vars
             $config['params'][] = $this->vars[$k];
         } else {
             // By name
             $config['params'][$k] = null;
         }
     }
     if (isset($config['params'])) {
         $config['params'] = ConfigHelper::toArray($config['params'], true, true);
     }
     // Add the callback's JavaScript representation
     $config['js'] = new Variant();
     $config['js']->set('JS', $this->js);
     return $config;
 }
 /**
  * @testdox The regexp has the Unicode modifier if notBefore contains a Unicode property
  */
 public function testNotBeforeUnicode()
 {
     $plugin = $this->configurator->plugins->load('Emoticons');
     $plugin->add('x', 'x');
     $plugin->notBefore = '\\pL';
     $config = $plugin->asConfig();
     ConfigHelper::filterVariants($config);
     $this->assertSame('/x(?!\\pL)/Su', $config['regexp']);
 }
 /**
  * @testdox asConfig() preserves aliased attributes' keys in a JS variant
  */
 public function testAsConfigAliasAttribute()
 {
     $plugin = $this->configurator->plugins->load('HTMLElements');
     $plugin->aliasAttribute('A', 'HREF', 'URL');
     $pluginConfig = $plugin->asConfig();
     ConfigHelper::filterVariants($pluginConfig, 'JS');
     $this->assertEquals(new Dictionary(['a' => new Dictionary(['href' => 'url'])]), $pluginConfig['aliases']);
 }
 public function getHelper()
 {
     $config = $this->asConfig();
     if (isset($config)) {
         $config = ConfigHelper::filterConfig($config, 'PHP');
     } else {
         $config = array('attrName' => $this->attrName, 'regexp' => '/(?!)/', 'tagName' => $this->tagName);
     }
     return new Helper($config);
 }
Beispiel #20
0
 public function asConfig()
 {
     $config = array('attrName' => $this->attrName, 'tagName' => $this->tagName);
     if (!empty($this->aliases)) {
         $aliases = \array_keys($this->aliases);
         $regexp = '/' . RegexpBuilder::fromList($aliases) . '/';
         $config['aliases'] = $this->aliases;
         $config['aliasesRegexp'] = new Regexp($regexp, \true);
         $quickMatch = ConfigHelper::generateQuickMatchFromList($aliases);
         if ($quickMatch !== \false) {
             $config['aliasesQuickMatch'] = $quickMatch;
         }
     }
     return $config;
 }
Beispiel #21
0
 /**
  * @testdox asConfig() uses target names as keys for closeParent
  */
 public function testAsConfigFlipsCloseParent()
 {
     $ruleset = new Ruleset();
     $ruleset->closeParent('X');
     $ruleset->closeParent('Y');
     $config = $ruleset->asConfig();
     ConfigHelper::filterVariants($config);
     $this->assertArrayHasKey('closeParent', $config);
     $this->assertArrayHasKey('X', $config['closeParent']);
     $this->assertArrayHasKey('Y', $config['closeParent']);
 }
Beispiel #22
0
 /**
  * @return array
  */
 public function asConfig()
 {
     if (!count($this->collection)) {
         return;
     }
     // Grab the emoticons from the collection
     $codes = array_keys(iterator_to_array($this->collection));
     // Build the regexp used to match emoticons
     $regexp = '/';
     if ($this->notAfter !== '') {
         $regexp .= '(?<!' . $this->notAfter . ')';
     }
     $regexp .= RegexpBuilder::fromList($codes);
     if ($this->notBefore !== '') {
         $regexp .= '(?!' . $this->notBefore . ')';
     }
     $regexp .= '/S';
     // Set the Unicode mode if Unicode properties are used
     if (preg_match('/\\\\[pP](?>\\{\\^?\\w+\\}|\\w\\w?)/', $regexp)) {
         $regexp .= 'u';
     }
     // Force the regexp to use atomic grouping for performance
     $regexp = preg_replace('/(?<!\\\\)((?>\\\\\\\\)*)\\(\\?:/', '$1(?>', $regexp);
     // Prepare the config array
     $config = ['quickMatch' => $this->quickMatch, 'regexp' => $regexp, 'tagName' => $this->tagName];
     // If notAfter is used, we need to create a JavaScript-specific regexp that does not use a
     // lookbehind assertion, and we add the notAfter subpattern to the config as a variant
     if ($this->notAfter !== '') {
         // Skip the first assertion by skipping the first N characters, where N equals the
         // length of $this->notAfter plus 1 for the first "/" and 5 for "(?<!)"
         $lpos = 6 + strlen($this->notAfter);
         $rpos = strrpos($regexp, '/');
         $jsRegexp = RegexpConvertor::toJS('/' . substr($regexp, $lpos, $rpos - $lpos) . '/', true);
         $config['regexp'] = new Variant($regexp);
         $config['regexp']->set('JS', $jsRegexp);
         $config['notAfter'] = new Variant();
         $config['notAfter']->set('JS', RegexpConvertor::toJS('/' . $this->notAfter . '/'));
     }
     // Try to find a quickMatch if none is set
     if ($this->quickMatch === false) {
         $config['quickMatch'] = ConfigHelper::generateQuickMatchFromList($codes);
     }
     return $config;
 }
 /**
  * @testdox asConfig() returns predefinedAttributes in a Dictionary
  */
 public function testAsConfigPreservesPredefinedAttributeNames()
 {
     $plugin = $this->configurator->plugins->load('BBCodes');
     $plugin->add('FOO')->predefinedAttributes['k'] = 'v';
     $config = $plugin->asConfig();
     ConfigHelper::filterVariants($config, 'JS');
     $this->assertInstanceOf('s9e\\TextFormatter\\Configurator\\JavaScript\\Dictionary', $config['bbcodes']['FOO']['predefinedAttributes']);
     $this->assertArrayHasKey('k', $config['bbcodes']['FOO']['predefinedAttributes']);
 }
 /**
  * @testdox Words using the default replacement do not appear in the replacements
  */
 public function testAsConfigDefaultReplacement()
 {
     $plugin = $this->configurator->plugins->load('Censor', ['defaultReplacement' => '**']);
     $plugin->add('apple', '**');
     $plugin->add('cherry', 'banana');
     $config = $plugin->asConfig();
     ConfigHelper::filterVariants($config);
     $this->assertSame([['/^cherry$/Diu', 'banana']], $config['replacements']);
 }
 public function asConfig()
 {
     return ConfigHelper::toArray(\get_object_vars($this));
 }
 /**
  * @return array|null This plugin's config, or NULL to disable this plugin
  */
 public function asConfig()
 {
     $properties = get_object_vars($this);
     unset($properties['configurator']);
     return ConfigHelper::toArray($properties);
 }
Beispiel #27
0
 /**
  * Generate and return the complete config array
  *
  * @return array
  */
 public function asConfig()
 {
     // Finalize the plugins' config
     $this->plugins->finalize();
     // Remove properties that shouldn't be turned into config arrays
     $properties = get_object_vars($this);
     unset($properties['attributeFilters']);
     unset($properties['bundleGenerator']);
     unset($properties['javascript']);
     unset($properties['rendering']);
     unset($properties['rulesGenerator']);
     unset($properties['registeredVars']);
     unset($properties['templateChecker']);
     unset($properties['templateNormalizer']);
     unset($properties['stylesheet']);
     // Create the config array
     $config = ConfigHelper::toArray($properties);
     $bitfields = RulesHelper::getBitfields($this->tags, $this->rootRules);
     // Save the root context
     $config['rootContext'] = $bitfields['root'];
     $config['rootContext']['flags'] = $config['rootRules']['flags'];
     // Save the registered vars (including the empty ones)
     $config['registeredVars'] = ConfigHelper::toArray($this->registeredVars, true);
     // Make sure those keys exist even if they're empty
     $config += ['plugins' => [], 'tags' => []];
     // Remove unused tags
     $config['tags'] = array_intersect_key($config['tags'], $bitfields['tags']);
     // Add the bitfield information to each tag
     foreach ($bitfields['tags'] as $tagName => $tagBitfields) {
         $config['tags'][$tagName] += $tagBitfields;
     }
     // Remove unused entries
     unset($config['rootRules']);
     return $config;
 }