class CodeFilter in Code Filter 8
Text filter for highlighting PHP source code.
Plugin annotation
@Filter(
id = "codefilter",
module = "codefilter",
title = @Translation("Code filter"),
type = Drupal\filter\Plugin\FilterInterface::TYPE_MARKUP_LANGUAGE,
settings = {
"nowrap_expand" = 0
}
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\filter\Plugin\FilterBase implements FilterInterface
- class \Drupal\codefilter\Plugin\Filter\CodeFilter
- class \Drupal\filter\Plugin\FilterBase implements FilterInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of CodeFilter
1 file declares its use of CodeFilter
- CodeFilterTest.php in src/
Tests/ CodeFilterTest.php
File
- src/
Plugin/ Filter/ CodeFilter.php, line 23
Namespace
Drupal\codefilter\Plugin\FilterView source
class CodeFilter extends FilterBase {
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$form['nowrap_expand'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Expand code boxes on hover.'),
'#description' => $this
->t('By default, code boxes inherit text wrapping from the active theme. With this setting, code boxes will not wrap, but will expand to full width on hover (with Javascript).'),
'#default_value' => $this->settings['nowrap_expand'],
];
return $form;
}
/**
* {@inheritdoc}
*/
public function tips($long = FALSE) {
if ($long) {
return $this
->t('To post pieces of code, surround them with <code>...</code> tags. For PHP code, you can use <?php ... ?>, which will also colour it based on syntax.');
}
else {
return $this
->t('You may post code using <code>...</code> (generic) or <?php ... ?> (highlighted PHP) tags.');
}
}
/**
* {@inheritdoc}
*/
public function process($text, $langcode) {
// Escape code tags to prevent other filters from acting on them.
$text = preg_replace_callback('@<code>(.+?)</code>@s', [
get_class($this),
'codeTagCallback',
], $text);
$text = preg_replace_callback('@[\\[<](\\?php)(.+?)(\\?)[\\]>]@s', [
get_class($this),
'phpTagCallback',
], $text);
// Replace code.
$text = preg_replace_callback('@\\[codefilter_code\\](.+?)\\[/codefilter_code\\]@s', [
get_class($this),
'processCodeCallback',
], $text);
$text = preg_replace_callback('@\\[codefilter_php\\](.+?)\\[/codefilter_php\\]@s', [
get_class($this),
'processPHPCallback',
], $text);
// A hack, so we can conditionally nowrap based on filter settings.
// @todo Refactor how replacements are done so we can do this more cleanly.
if ($this->settings['nowrap_expand']) {
$text = str_replace('class="codeblock"', 'class="codeblock nowrap-expand"', $text);
}
return new FilterProcessResult($text);
}
/**
* Callback to escape content of <code> tags.
*
* @param array $matches
* An array of matches passed by preg_replace_callback().
*
* @return string
* A formatted string.
*/
public static function codeTagCallback(array $matches) {
return self::escape($matches[1], 'code');
}
/**
* Callback to escape content of <?php ?>, [?php ?], <% %>, and [% %] tags.
*
* @param array $matches
* An array of matches passed by preg_replace_callback().
*
* @return string
* A formatted string.
*/
public static function phpTagCallback(array $matches) {
return self::escape($matches[2], 'php');
}
/**
* Callback to replace content of the <code> elements.
*
* @param array $matches
* An array of matches passed by preg_replace_callback().
*
* @return string
* A formatted string.
*/
public static function processCodeCallback(array $matches) {
return self::processCode($matches[1]);
}
/**
* Callback to replace content of the <?php ?> elements.
*
* @param array $matches
* An array of matches passed by preg_replace_callback().
*
* @return string
* A formatted string.
*/
public static function processPHPCallback(array $matches) {
return self::processPHP($matches[1]);
}
/**
* Escape code blocks.
*
* @param string $text
* The string to escape.
* @param string $type
* The type of code block, either 'code' or 'php'.
*
* @return string
* The escaped string.
*/
public static function escape($text, $type = 'code') {
// Note, pay attention to odd preg_replace-with-/e behaviour on slashes.
$text = Html::escape(str_replace('\\"', '"', $text));
// Protect newlines from line break converter.
$text = str_replace([
"\r",
"\n",
], [
'',
' ',
], $text);
// Add codefilter escape tags.
$text = "[codefilter_{$type}]{$text}[/codefilter_{$type}]";
return $text;
}
/**
* Processes chunks of escaped code into HTML.
*/
public static function processCode($text) {
// Undo linebreak escaping.
$text = str_replace(' ', "\n", $text);
// Inline or block level piece?
$multiline = strpos($text, "\n") !== FALSE;
// Note, pay attention to odd preg_replace-with-/e behaviour on slashes.
$text = preg_replace("/^\n/", '', preg_replace('@</?(br|p)\\s*/?>@', '', str_replace('\\"', '"', $text)));
// Trim leading and trailing linebreaks.
$text = trim($text, "\n");
// Escape newlines.
$text = nl2br($text);
// PHP code in regular code.
$text = preg_replace_callback('/<\\?php.+?\\?>/s', [
get_class(),
'processPHPInline',
], $text);
$text = '<code>' . self::fixSpaces(str_replace(' ', ' ', $text)) . '</code>';
$text = $multiline ? '<div class="codeblock">' . $text . '</div>' : $text;
// Remove newlines to avoid clashing with the linebreak filter.
return str_replace("\n", '', $text);
}
/**
* Helper function for processCode().
*/
public static function processPHPInline($matches) {
// Undo nl2br.
$text = str_replace('<br />', '', $matches[0]);
// Decode entities (the highlighter re-entifies) and highlight text.
$text = highlight_string(Html::decodeEntities($text), 1);
// Remove PHPs own added code tags.
$text = str_replace([
'<code>',
'</code>',
"\n",
], [
'',
'',
'',
], $text);
return $text;
}
/**
* Processes chunks of escaped PHP code into HTML.
*/
public static function processPHP($text) {
// Note, pay attention to odd preg_replace-with-/e behaviour on slashes.
// Undo possible linebreak filter conversion.
$text = preg_replace('@</?(br|p)\\s*/?>@', '', str_replace('\\"', '"', $text));
// Undo the escaping in the prepare step.
$text = Html::decodeEntities($text);
// Trim leading and trailing linebreaks.
$text = trim($text, "\r\n");
// Highlight as PHP.
$text = '<div class="codeblock">' . highlight_string("<?php\n{$text}\n?>", 1) . '</div>';
// Remove newlines to avoid clashing with the linebreak filter.
$text = str_replace("\n", '', $text);
return self::fixSpaces($text);
}
/**
* Replace html space elements with literal space characters.
*
* @param string $text
* A string to fix spaces for.
*
* @return string
* A formatted string.
*/
public static function fixSpaces($text) {
$text = preg_replace('@ (?! )@', ' ', $text);
// A single space before text is ignored by browsers. If a single space
// follows a break tag, replace it with a non-breaking space.
$text = preg_replace('@<br /> ([^ ])@', '<br /> $1', $text);
return $text;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
CodeFilter:: |
public static | function | Callback to escape content of <code> tags. | |
CodeFilter:: |
public static | function | Escape code blocks. | |
CodeFilter:: |
public static | function | Replace html space elements with literal space characters. | |
CodeFilter:: |
public static | function | Callback to escape content of <?php ?>, [?php ?], <% %>, and [% %] tags. | |
CodeFilter:: |
public | function |
Performs the filter processing. Overrides FilterInterface:: |
|
CodeFilter:: |
public static | function | Processes chunks of escaped code into HTML. | |
CodeFilter:: |
public static | function | Callback to replace content of the <code> elements. | |
CodeFilter:: |
public static | function | Processes chunks of escaped PHP code into HTML. | |
CodeFilter:: |
public static | function | Callback to replace content of the <?php ?> elements. | |
CodeFilter:: |
public static | function | Helper function for processCode(). | |
CodeFilter:: |
public | function |
Generates a filter's settings form. Overrides FilterBase:: |
|
CodeFilter:: |
public | function |
Generates a filter's tip. Overrides FilterBase:: |
|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FilterBase:: |
public | property | The name of the provider that owns this filter. | |
FilterBase:: |
public | property | An associative array containing the configured settings of this filter. | |
FilterBase:: |
public | property | A Boolean indicating whether this filter is enabled. | |
FilterBase:: |
public | property | The weight of this filter compared to others in a filter collection. | |
FilterBase:: |
public | function |
Calculates dependencies for the configured plugin. Overrides DependentPluginInterface:: |
1 |
FilterBase:: |
public | function |
Gets default configuration for this plugin. Overrides ConfigurableInterface:: |
|
FilterBase:: |
public | function |
Gets this plugin's configuration. Overrides ConfigurableInterface:: |
|
FilterBase:: |
public | function |
Returns the administrative description for this filter plugin. Overrides FilterInterface:: |
|
FilterBase:: |
public | function |
Returns HTML allowed by this filter's configuration. Overrides FilterInterface:: |
4 |
FilterBase:: |
public | function |
Returns the administrative label for this filter plugin. Overrides FilterInterface:: |
|
FilterBase:: |
public | function |
Returns the processing type of this filter plugin. Overrides FilterInterface:: |
|
FilterBase:: |
public | function |
Prepares the text for processing. Overrides FilterInterface:: |
|
FilterBase:: |
public | function |
Sets the configuration for this plugin instance. Overrides ConfigurableInterface:: |
1 |
FilterBase:: |
public | function |
Constructs a \Drupal\Component\Plugin\PluginBase object. Overrides PluginBase:: |
4 |
FilterInterface:: |
constant | HTML tag and attribute restricting filters to prevent XSS attacks. | ||
FilterInterface:: |
constant | Non-HTML markup language filters that generate HTML. | ||
FilterInterface:: |
constant | Irreversible transformation filters. | ||
FilterInterface:: |
constant | Reversible transformation filters. | ||
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |