diff options
Diffstat (limited to 'vendor/jfcherng/php-diff/src/Renderer/AbstractRenderer.php')
-rw-r--r-- | vendor/jfcherng/php-diff/src/Renderer/AbstractRenderer.php | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/vendor/jfcherng/php-diff/src/Renderer/AbstractRenderer.php b/vendor/jfcherng/php-diff/src/Renderer/AbstractRenderer.php new file mode 100644 index 0000000..953cb9a --- /dev/null +++ b/vendor/jfcherng/php-diff/src/Renderer/AbstractRenderer.php @@ -0,0 +1,246 @@ +<?php + +declare(strict_types=1); + +namespace Jfcherng\Diff\Renderer; + +use Jfcherng\Diff\Differ; +use Jfcherng\Diff\SequenceMatcher; +use Jfcherng\Diff\Utility\Language; + +/** + * Base class for diff renderers. + */ +abstract class AbstractRenderer implements RendererInterface +{ + /** + * @var array information about this renderer + */ + public const INFO = [ + 'desc' => 'default_desc', + 'type' => 'default_type', + ]; + + /** + * @var bool Is this renderer pure text? + */ + public const IS_TEXT_RENDERER = true; + + /** + * @var string[] array of the opcodes and their corresponding symbols + */ + public const SYMBOL_MAP = [ + SequenceMatcher::OP_DEL => '-', + SequenceMatcher::OP_EQ => ' ', + SequenceMatcher::OP_INS => '+', + SequenceMatcher::OP_REP => '!', + ]; + + /** + * @var Language the language translation object + */ + protected $t; + + /** + * If the input "changes" have `<ins>...</ins>` or `<del>...</del>`, + * which means they have been processed, then `false`. Otherwise, `true`. + * + * @var bool + */ + protected $changesAreRaw = true; + + /** + * @var array array of the default options that apply to this renderer + */ + protected static $defaultOptions = [ + // how detailed the rendered HTML in-line diff is? (none, line, word, char) + 'detailLevel' => 'line', + // renderer language: eng, cht, chs, jpn, ... + // or an array which has the same keys with a language file + // check the "Custom Language" section in the readme for more advanced usage + 'language' => 'eng', + // show line numbers in HTML renderers + 'lineNumbers' => true, + // show a separator between different diff hunks in HTML renderers + 'separateBlock' => true, + // show the (table) header + 'showHeader' => true, + // convert spaces/tabs into HTML codes like `<span class="ch sp"> </span>` + // and the frontend is responsible for rendering them with CSS. + // when using this, "spacesToNbsp" should be false and "tabSize" is not respected. + 'spaceToHtmlTag' => false, + // the frontend HTML could use CSS "white-space: pre;" to visualize consecutive whitespaces + // but if you want to visualize them in the backend with " ", you can set this to true + 'spacesToNbsp' => false, + // HTML renderer tab width (negative = do not convert into spaces) + 'tabSize' => 4, + // this option is currently only for the Combined renderer. + // it determines whether a replace-type block should be merged or not + // depending on the content changed ratio, which values between 0 and 1. + 'mergeThreshold' => 0.8, + // this option is currently only for the Unified and the Context renderers. + // RendererConstant::CLI_COLOR_AUTO = colorize the output if possible (default) + // RendererConstant::CLI_COLOR_ENABLE = force to colorize the output + // RendererConstant::CLI_COLOR_DISABLE = force not to colorize the output + 'cliColorization' => RendererConstant::CLI_COLOR_AUTO, + // this option is currently only for the Json renderer. + // internally, ops (tags) are all int type but this is not good for human reading. + // set this to "true" to convert them into string form before outputting. + 'outputTagAsString' => false, + // this option is currently only for the Json renderer. + // it controls how the output JSON is formatted. + // see availabe options on https://www.php.net/manual/en/function.json-encode.php + 'jsonEncodeFlags' => \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE, + // this option is currently effective when the "detailLevel" is "word" + // characters listed in this array can be used to make diff segments into a whole + // for example, making "<del>good</del>-<del>looking</del>" into "<del>good-looking</del>" + // this should bring better readability but set this to empty array if you do not want it + 'wordGlues' => ['-', ' '], + // change this value to a string as the returned diff if the two input strings are identical + 'resultForIdenticals' => null, + // extra HTML classes added to the DOM of the diff container + 'wrapperClasses' => ['diff-wrapper'], + ]; + + /** + * @var array array containing the user applied and merged default options for the renderer + */ + protected $options = []; + + /** + * The constructor. Instantiates the rendering engine and if options are passed, + * sets the options for the renderer. + * + * @param array $options optionally, an array of the options for the renderer + */ + public function __construct(array $options = []) + { + $this->setOptions($options); + } + + /** + * Set the options of the renderer to those supplied in the passed in array. + * Options are merged with the default to ensure that there aren't any missing + * options. + * + * @param array $options the options + * + * @return static + */ + public function setOptions(array $options): self + { + $newOptions = $options + static::$defaultOptions; + + $this->updateLanguage( + $this->options['language'] ?? '', + $newOptions['language'] + ); + + $this->options = $newOptions; + + return $this; + } + + /** + * Get the options. + * + * @return array the options + */ + public function getOptions(): array + { + return $this->options; + } + + /** + * {@inheritdoc} + * + * @final + * + * @todo mark this method with "final" in the next major release + * + * @throws \InvalidArgumentException + */ + public function getResultForIdenticals(): string + { + $custom = $this->options['resultForIdenticals']; + + if (isset($custom) && !\is_string($custom)) { + throw new \InvalidArgumentException('renderer option `resultForIdenticals` must be null or string.'); + } + + return $custom ?? $this->getResultForIdenticalsDefault(); + } + + /** + * Get the renderer default result when the old and the new are the same. + */ + abstract public function getResultForIdenticalsDefault(): string; + + /** + * {@inheritdoc} + */ + final public function render(Differ $differ): string + { + $this->changesAreRaw = true; + // the "no difference" situation may happen frequently + return $differ->getOldNewComparison() === 0 + ? $this->getResultForIdenticals() + : $this->renderWorker($differ); + } + + /** + * {@inheritdoc} + */ + final public function renderArray(array $differArray): string + { + $this->changesAreRaw = false; + + return $this->renderArrayWorker($differArray); + } + + /** + * The real worker for self::render(). + * + * @param Differ $differ the differ object + */ + abstract protected function renderWorker(Differ $differ): string; + + /** + * The real worker for self::renderArray(). + * + * @param array[][] $differArray the differ array + */ + abstract protected function renderArrayWorker(array $differArray): string; + + /** + * Update the Language object. + * + * @param string|string[] $old the old language + * @param string|string[] $new the new language + * + * @return static + */ + protected function updateLanguage($old, $new): self + { + if (!isset($this->t) || $old !== $new) { + $this->t = new Language($new); + } + + return $this; + } + + /** + * A shorthand to do translation. + * + * @param string $text The text + * @param bool $escapeHtml Escape the translated text for HTML? + * + * @return string the translated text + */ + protected function _(string $text, bool $escapeHtml = true): string + { + $text = $this->t->translate($text); + + return $escapeHtml ? \htmlspecialchars($text) : $text; + } +} |