sistemazione composer install

This commit is contained in:
mariano
2026-05-22 14:13:33 +02:00
parent ad42773519
commit ed29fbc62d
252 changed files with 52727 additions and 13 deletions
+21
View File
@@ -0,0 +1,21 @@
# Demo
Note that
- All `composer`-related commands are run in this project's root directory.
That is php-diff directory rather than this `example` directory.
- You can change differ/renderer options in `demo_base.php`.
- Change contents of `old_file.txt` and `new_file.txt` to test different text.
To run demo, you have to first install dependencies via `composer install`.
## Web Environment
To run `demo_web.php` on your local machine, you can follow steps below.
1. Start PHP development server via `composer run-script server`.
1. Visit `http://localhost:12388/demo_web.php` with a web browser.
## Cli Environment
Just run `php demo_cli.php`.
+82
View File
@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
include __DIR__ . '/../vendor/autoload.php';
use Jfcherng\Diff\Differ;
use Jfcherng\Diff\Renderer\RendererConstant;
// the two sample files for comparison
$oldFile = __DIR__ . '/old_file.txt';
$newFile = __DIR__ . '/new_file.txt';
$oldString = file_get_contents($oldFile);
$newString = file_get_contents($newFile);
// options for Diff class
$diffOptions = [
// show how many neighbor lines
// Differ::CONTEXT_ALL can be used to show the whole file
'context' => 1,
// ignore case difference
'ignoreCase' => false,
// ignore line ending difference
'ignoreLineEnding' => false,
// ignore whitespace difference
'ignoreWhitespace' => false,
// if the input sequence is too long, it will just gives up (especially for char-level diff)
'lengthLimit' => 2000,
// if truthy, when inputs are identical, the whole inputs will be rendered in the output
'fullContextIfIdentical' => false,
];
// options for renderer class
$rendererOptions = [
// how detailed the rendered HTML 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 "&nbsp;", 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 available 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'],
];
+40
View File
@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
include __DIR__ . '/demo_base.php';
use Jfcherng\Diff\DiffHelper;
use Jfcherng\Utility\CliColor;
$colorStyles = [
'section' => ['f_black', 'b_cyan'],
];
$manyNewlines = "\n\n\n\n";
echo CliColor::color("Unified Diff\n============", $colorStyles['section']) . "\n\n";
// generate a unified diff
$unifiedResult = DiffHelper::calculate(
$oldString,
$newString,
'Unified',
$diffOptions,
$rendererOptions,
);
echo $unifiedResult . $manyNewlines;
echo CliColor::color("Context Diff\n============", $colorStyles['section']) . "\n\n";
// generate a context diff
$contextResult = DiffHelper::calculate(
$oldString,
$newString,
'Context',
$diffOptions,
$rendererOptions,
);
echo $contextResult . $manyNewlines;
+242
View File
@@ -0,0 +1,242 @@
<?php
declare(strict_types=1);
include __DIR__ . '/demo_base.php';
use Jfcherng\Diff\DiffHelper;
use Jfcherng\Diff\Factory\RendererFactory;
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>jfcherng/php-diff - Examples</title>
<!-- Prism -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism-okaidia.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/line-numbers/prism-line-numbers.min.css" />
<style type="text/css">
html {
font-size: 13px;
}
.token.coord {
color: #6cf;
}
.token.diff.bold {
color: #fb0;
font-weight: normal;
}
<?= DiffHelper::getStyleSheet(); ?>
</style>
</head>
<body>
<h1>None-level Diff</h1>
<?php
// demo the no-inline-detail diff
$inlineResult = DiffHelper::calculate(
$oldString,
$newString,
'Inline',
$diffOptions,
['detailLevel' => 'none'] + $rendererOptions,
);
echo $inlineResult;
?>
<h1>Line-level Diff (Default)</h1>
<?php
// demo the word-level diff
$inlineResult = DiffHelper::calculate(
$oldString,
$newString,
'Inline',
$diffOptions,
['detailLevel' => 'line'] + $rendererOptions,
);
echo $inlineResult;
?>
<h1>Word-level Diff</h1>
<?php
// demo the word-level diff
$inlineResult = DiffHelper::calculate(
$oldString,
$newString,
'Inline',
$diffOptions,
['detailLevel' => 'word'] + $rendererOptions,
);
echo $inlineResult;
?>
<h1>Character-level Diff</h1>
<?php
// demo the character-level diff
$inlineResult = DiffHelper::calculate(
$oldString,
$newString,
'Inline',
$diffOptions,
['detailLevel' => 'char'] + $rendererOptions,
);
echo $inlineResult;
?>
<h1>Side by Side Diff</h1>
<?php
// generate a side by side diff
$sideBySideResult = DiffHelper::calculateFiles(
$oldFile,
$newFile,
'SideBySide',
$diffOptions,
$rendererOptions,
);
echo $sideBySideResult;
?>
<h1>Inline Diff</h1>
<?php
// generate an inline diff
$inlineResult = DiffHelper::calculateFiles(
$oldFile,
$newFile,
'Inline',
$diffOptions,
$rendererOptions,
);
echo $inlineResult;
?>
<h1>Combined Diff</h1>
<?php
// generate a combined diff
$sideBySideResult = DiffHelper::calculateFiles(
$oldFile,
$newFile,
'Combined',
$diffOptions,
$rendererOptions,
);
echo $sideBySideResult;
?>
<h1>Unified Diff</h1>
<pre><code class="language-diff line-numbers"><?php
// generate a unified diff
$unifiedResult = DiffHelper::calculateFiles(
$oldFile,
$newFile,
'Unified',
$diffOptions,
$rendererOptions,
);
echo htmlspecialchars($unifiedResult);
?></code></pre>
<h1>Context Diff</h1>
<pre><code class="language-diff line-numbers"><?php
// generate a context diff
$contextResult = DiffHelper::calculateFiles(
$oldFile,
$newFile,
'Context',
$diffOptions,
$rendererOptions,
);
echo htmlspecialchars($contextResult);
?></code></pre>
<?php
// change JSON output settings for better human reading
$rendererOptions['outputTagAsString'] = true;
$rendererOptions['jsonEncodeFlags'] |= \JSON_PRETTY_PRINT;
?>
<h1>Text JSON Diff</h1>
<pre><code class="language-json line-numbers"><?php
// generate a plain text JSON diff
$jsonResult = DiffHelper::calculateFiles(
$oldFile,
$newFile,
'JsonText',
$diffOptions,
$rendererOptions,
);
echo htmlspecialchars($jsonResult);
?></code></pre>
<h1>HTML JSON Diff</h1>
<pre><code class="language-json line-numbers"><?php
// generate a HTML JSON diff
$jsonResult = DiffHelper::calculateFiles(
$oldFile,
$newFile,
'JsonHtml',
$diffOptions,
$rendererOptions,
);
echo htmlspecialchars($jsonResult);
?></code></pre>
<h1>HTML Diff from the Result of JSON Diff</h1>
<?php
$jsonArray = json_decode($jsonResult, true);
$htmlRenderer = RendererFactory::make('Inline', $rendererOptions);
$inlineResult = $htmlRenderer->renderArray($jsonArray);
echo $inlineResult;
?>
<!-- Prism -->
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/prism.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-diff.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-json.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/line-numbers/prism-line-numbers.min.js"></script>
</body>
</html>
+122
View File
@@ -0,0 +1,122 @@
.diff-wrapper.diff {
--tab-size: 4;
background: repeating-linear-gradient(-45deg, whitesmoke, whitesmoke 0.5em, #e8e8e8 0.5em, #e8e8e8 1em);
border-collapse: collapse;
border-spacing: 0;
border: 1px solid black;
color: black;
empty-cells: show;
font-family: monospace;
font-size: 13px;
width: 100%;
word-break: break-all;
}
.diff-wrapper.diff th {
font-weight: 700;
cursor: default;
-webkit-user-select: none;
user-select: none;
}
.diff-wrapper.diff td {
vertical-align: baseline;
}
.diff-wrapper.diff td,
.diff-wrapper.diff th {
border-collapse: separate;
border: none;
padding: 1px 2px;
background: #fff;
}
.diff-wrapper.diff td:empty:after,
.diff-wrapper.diff th:empty:after {
content: " ";
visibility: hidden;
}
.diff-wrapper.diff td a,
.diff-wrapper.diff th a {
color: #000;
cursor: inherit;
pointer-events: none;
}
.diff-wrapper.diff thead th {
background: #a6a6a6;
border-bottom: 1px solid black;
padding: 4px;
text-align: left;
}
.diff-wrapper.diff tbody.skipped {
border-top: 1px solid black;
}
.diff-wrapper.diff tbody.skipped td,
.diff-wrapper.diff tbody.skipped th {
display: none;
}
.diff-wrapper.diff tbody th {
background: #cccccc;
border-right: 1px solid black;
text-align: right;
vertical-align: top;
width: 4em;
}
.diff-wrapper.diff tbody th.sign {
background: #fff;
border-right: none;
padding: 1px 0;
text-align: center;
width: 1em;
}
.diff-wrapper.diff tbody th.sign.del {
background: #fbe1e1;
}
.diff-wrapper.diff tbody th.sign.ins {
background: #e1fbe1;
}
.diff-wrapper.diff.diff-html {
white-space: pre-wrap;
tab-size: var(--tab-size);
}
.diff-wrapper.diff.diff-html .ch {
line-height: 1em;
background-clip: border-box;
background-repeat: repeat-x;
background-position: left center;
}
.diff-wrapper.diff.diff-html .ch.sp {
background-image: url('data:image/svg+xml,%3Csvg preserveAspectRatio="xMinYMid meet" viewBox="0 0 12 24" xmlns="http://www.w3.org/2000/svg"%3E%3Cpath d="M4.5 11C4.5 10.1716 5.17157 9.5 6 9.5C6.82843 9.5 7.5 10.1716 7.5 11C7.5 11.8284 6.82843 12.5 6 12.5C5.17157 12.5 4.5 11.8284 4.5 11Z" fill="rgba%2860, 60, 60, 50%25%29"/%3E%3C/svg%3E');
background-size: 1ch 1.25em;
}
.diff-wrapper.diff.diff-html .ch.tab {
background-image: url('data:image/svg+xml,%3Csvg preserveAspectRatio="xMinYMid meet" viewBox="0 0 12 24" xmlns="http://www.w3.org/2000/svg"%3E%3Cpath d="M9.5 10.44L6.62 8.12L7.32 7.26L12.04 11V11.44L7.28 14.9L6.62 13.9L9.48 11.78H0V10.44H9.5Z" fill="rgba%2860, 60, 60, 50%25%29"/%3E%3C/svg%3E');
background-size: calc(var(--tab-size) * 1ch) 1.25em;
background-position: 2px center;
}
.diff-wrapper.diff.diff-html .change.change-eq .old,
.diff-wrapper.diff.diff-html .change.change-eq .new {
background: #fff;
}
.diff-wrapper.diff.diff-html .change .old {
background: #fbe1e1;
}
.diff-wrapper.diff.diff-html .change .new {
background: #e1fbe1;
}
.diff-wrapper.diff.diff-html .change .rep {
background: #fef6d9;
}
.diff-wrapper.diff.diff-html .change .old.none,
.diff-wrapper.diff.diff-html .change .new.none,
.diff-wrapper.diff.diff-html .change .rep.none {
background: transparent;
cursor: not-allowed;
}
.diff-wrapper.diff.diff-html .change ins,
.diff-wrapper.diff.diff-html .change del {
font-weight: bold;
text-decoration: none;
}
.diff-wrapper.diff.diff-html .change ins {
background: #94f094;
}
.diff-wrapper.diff.diff-html .change del {
background: #f09494;
}
+193
View File
@@ -0,0 +1,193 @@
// You can compile this with https://www.sassmeister.com
$diff-bg-color: #fff !default;
$diff-text-color: invert($diff-bg-color) !default;
$diff-bg-color-ins-base: #8e8 !default;
$diff-bg-color-del-base: #e88 !default;
$diff-bg-color-rep-base: #fbdb65 !default;
$diff-op-highlight-ratio: 90% !default;
$diff-op-normal-ratio: 25% !default;
// emphasized colors for detailed inline difference
$diff-bg-color-ins-highlight: mix($diff-bg-color-ins-base, $diff-bg-color, $diff-op-highlight-ratio) !default;
$diff-bg-color-del-highlight: mix($diff-bg-color-del-base, $diff-bg-color, $diff-op-highlight-ratio) !default;
// colors for operation rows
$diff-bg-color-ins: mix($diff-bg-color-ins-base, $diff-bg-color, $diff-op-normal-ratio) !default;
$diff-bg-color-del: mix($diff-bg-color-del-base, $diff-bg-color, $diff-op-normal-ratio) !default;
$diff-bg-color-rep: mix($diff-bg-color-rep-base, $diff-bg-color, $diff-op-normal-ratio) !default;
$diff-table-head-color: mix($diff-bg-color, $diff-text-color, 65%) !default;
$diff-table-sidebar-color: mix($diff-bg-color, $diff-text-color, 80%) !default;
$diff-border-color: $diff-text-color !default;
// color for the nonexistent block
// for example, there are a deleted line that has no corresponding one
$diff-bg-color-none-block: mix($diff-bg-color, $diff-table-sidebar-color, 80%) !default;
$diff-bg-color-none-block-alternative: mix($diff-bg-color, $diff-table-sidebar-color, 55%) !default;
// symbol images
$img-space: 'data:image/svg+xml,%3Csvg preserveAspectRatio="xMinYMid meet" viewBox="0 0 12 24" xmlns="http://www.w3.org/2000/svg"%3E%3Cpath d="M4.5 11C4.5 10.1716 5.17157 9.5 6 9.5C6.82843 9.5 7.5 10.1716 7.5 11C7.5 11.8284 6.82843 12.5 6 12.5C5.17157 12.5 4.5 11.8284 4.5 11Z" fill="rgba%2860, 60, 60, 50%25%29"/%3E%3C/svg%3E' !default;
$img-tab: 'data:image/svg+xml,%3Csvg preserveAspectRatio="xMinYMid meet" viewBox="0 0 12 24" xmlns="http://www.w3.org/2000/svg"%3E%3Cpath d="M9.5 10.44L6.62 8.12L7.32 7.26L12.04 11V11.44L7.28 14.9L6.62 13.9L9.48 11.78H0V10.44H9.5Z" fill="rgba%2860, 60, 60, 50%25%29"/%3E%3C/svg%3E' !default;
.diff-wrapper.diff {
--tab-size: 4;
background: repeating-linear-gradient(
-45deg,
$diff-bg-color-none-block,
$diff-bg-color-none-block 0.5em,
$diff-bg-color-none-block-alternative 0.5em,
$diff-bg-color-none-block-alternative 1em
);
border-collapse: collapse;
border-spacing: 0;
border: 1px solid $diff-border-color;
color: $diff-text-color;
empty-cells: show;
font-family: monospace;
font-size: 13px;
width: 100%;
word-break: break-all;
th {
font-weight: 700;
cursor: default;
-webkit-user-select: none;
user-select: none;
}
td {
vertical-align: baseline;
}
td,
th {
border-collapse: separate;
border: none;
padding: 1px 2px;
background: $diff-bg-color;
// make empty cell has height
&:empty:after {
content: ' ';
visibility: hidden;
}
a {
color: #000;
cursor: inherit;
pointer-events: none;
}
}
thead th {
background: $diff-table-head-color;
border-bottom: 1px solid $diff-border-color;
padding: 4px;
text-align: left;
}
tbody {
&.skipped {
border-top: 1px solid $diff-border-color;
td,
th {
display: none;
}
}
th {
background: $diff-table-sidebar-color;
border-right: 1px solid $diff-border-color;
text-align: right;
vertical-align: top;
width: 4em;
&.sign {
background: $diff-bg-color;
border-right: none;
padding: 1px 0;
text-align: center;
width: 1em;
&.del {
background: $diff-bg-color-del;
}
&.ins {
background: $diff-bg-color-ins;
}
}
}
}
&.diff-html {
white-space: pre-wrap;
tab-size: var(--tab-size);
.ch {
line-height: 1em;
background-clip: border-box;
background-repeat: repeat-x;
background-position: left center;
&.sp {
background-image: url($img-space);
background-size: 1ch 1.25em;
}
&.tab {
background-image: url($img-tab);
background-size: calc(var(--tab-size) * 1ch) 1.25em;
background-position: 2px center;
}
}
.change {
&.change-eq {
.old,
.new {
background: $diff-bg-color;
}
}
.old {
background: $diff-bg-color-del;
}
.new {
background: $diff-bg-color-ins;
}
.rep {
background: $diff-bg-color-rep;
}
.old,
.new,
.rep {
&.none {
background: transparent;
cursor: not-allowed;
}
}
ins,
del {
font-weight: bold;
text-decoration: none;
}
ins {
background: $diff-bg-color-ins-highlight;
}
del {
background: $diff-bg-color-del-highlight;
}
}
}
}
+19
View File
@@ -0,0 +1,19 @@
<div>Hello World! Bad-tempered.</div>
~~~~~~~~~~~~~~~~~~~
Let's add a new line here.
X
Y
Just a context separator. 1
M
N
Do you know in Japanese, "魚の缶詰" means fish can.
Tab visualization test.
G
Say hello to my neighbors.
A
Just a context separator. 2
B
Donec rutrum test.
There is a new inserted line.
C
Sed dolor lorem ipsum hendrerit.
+18
View File
@@ -0,0 +1,18 @@
<p>Hello World! Good-looking.</p>
~~~~~~~~~~~~~~~~~~~
X
Y
Just a context separator. 1
M
N
Do you know in Chinese, "金槍魚罐頭" means tuna can.
Tab visualization test.
G
// remember to delete this line
Say hello to my neighbors.
A
Just a context separator. 2
B
Donec rutrum.
C
Sed dictum lorem ipsum.