Skip to content

Commit 1dcef3d

Browse files
committed
Now formatting is kept through sentences when breaking a paragraph.
1 parent d0f5a50 commit 1dcef3d

File tree

2 files changed

+63
-21
lines changed

2 files changed

+63
-21
lines changed

src/S2/Rose/Helper/StringHelper.php

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,19 @@ public static function sentencesFromText(string $text, bool $hasFormatting): arr
4545
$substrings = str_replace("", ' ', $substrings);
4646

4747
if ($hasFormatting) {
48-
// We keep the formatting scope within a single sentence.
48+
// We keep the formatting scope through several sentences.
4949
//
5050
// For example, consider the input: 'Sentence <i>1. Sentence 2. Sentence</i> 3.'
51-
// After processing, it becomes ['Sentence <i>1.</i>', 'Sentence 2.', '<i>Sentence</i> 3.'].
52-
//
53-
// This approach is reasonable because individual sentences are typically joined into snippets,
54-
// and preserving formatting across multiple sentences may not be meaningful.
55-
array_walk($substrings, static function (string &$text) {
56-
$text = self::fixUnbalancedInternalFormatting($text);
51+
// After processing, it becomes ['Sentence <i>1.</i>', '<i>Sentence 2.</i>', '<i>Sentence</i> 3.'].
52+
$tagsFromPrevSentence = [];
53+
array_walk($substrings, static function (string &$text) use (&$tagsFromPrevSentence) {
54+
foreach (array_reverse($tagsFromPrevSentence) as $possibleTag => $num) {
55+
if ($num > 0) {
56+
$text = str_repeat('\\' . $possibleTag, $num) . $text;
57+
$tagsFromPrevSentence[$possibleTag] = 0;
58+
}
59+
}
60+
$text = self::fixUnbalancedInternalFormatting($text, $tagsFromPrevSentence);
5761
});
5862
}
5963

@@ -101,11 +105,11 @@ public static function clearInternalFormatting(string $text): string
101105
]);
102106
}
103107

104-
public static function fixUnbalancedInternalFormatting(string $text): string
108+
public static function fixUnbalancedInternalFormatting(string $text, array &$tagsNum): string
105109
{
106110
preg_match_all('#\\\\([' . self::FORMATTING_SYMBOLS . '])#i', $text, $matches);
107111

108-
$tagsNum = [];
112+
// $tagsNum = [];
109113
foreach ($matches[1] as $match) {
110114
$lowerMatch = strtolower($match);
111115
$tagsNum[$lowerMatch] = ($tagsNum[$lowerMatch] ?? 0) + ($match === $lowerMatch ? 1 : -1);
@@ -118,8 +122,7 @@ public static function fixUnbalancedInternalFormatting(string $text): string
118122
$result = str_repeat('\\' . $possibleTag, -$num) . $result;
119123
}
120124
}
121-
$tagsNum = array_reverse($tagsNum);
122-
foreach ($tagsNum as $possibleTag => $num) {
125+
foreach (array_reverse($tagsNum) as $possibleTag => $num) {
123126
if ($num > 0) {
124127
$result .= str_repeat('\\' . strtoupper($possibleTag), $num);
125128
}

tests/unit/Rose/Helper/StringHelperTest.php

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php declare(strict_types=1);
22
/**
3-
* @copyright 2023 Roman Parpalak
3+
* @copyright 2023-2024 Roman Parpalak
44
* @license MIT
55
*/
66

@@ -17,9 +17,9 @@ class StringHelperTest extends Unit
1717
/**
1818
* @dataProvider sentenceDataProvider
1919
*/
20-
public function testSentences(string $text, array $sentences): void
20+
public function testSentences(string $text, array $sentences, bool $hasFormatting = false): void
2121
{
22-
foreach (StringHelper::sentencesFromText($text, false) as $i => $str) {
22+
foreach (StringHelper::sentencesFromText($text, $hasFormatting) as $i => $str) {
2323
$this->assertEquals($sentences[$i], $str);
2424
}
2525
}
@@ -36,6 +36,9 @@ public function sentenceDataProvider(): array
3636
'1, 2, 3 и т. д.',
3737
'Цифры, буквы, и т. п., могут встретиться.',
3838
]],
39+
['Sentence \i1. Sentence 2. Sentence\I 3.', ['Sentence \i1.\I', '\iSentence 2.\I', '\iSentence\I 3.'], true],
40+
['Sentence \i1. Sentence 2. Sentence\B 3.', ['Sentence \i1.\I', '\iSentence 2.\I', '\b\iSentence\B 3.\I'], true],
41+
['\i\uSentence \b1\B. Sentence 2. Sentence 3.\U\I', ['\i\uSentence \b1\B.\U\I', '\i\uSentence 2.\U\I', '\i\uSentence 3.\U\I'], true],
3942
[
4043
'Поезд отправился из пункта А в пункт Б. Затем вернулся назад.',
4144
[
@@ -97,13 +100,49 @@ public function sentenceDataProvider(): array
97100
];
98101
}
99102

100-
public function testFixUnbalancedInternalFormatting(): void
103+
/**
104+
* @dataProvider unbalancedInternalFormattingDataProvider
105+
*/
106+
public function testFixUnbalancedInternalFormatting(string $text, string $expected, array $expectedTags): void
107+
{
108+
$tags = [];
109+
$this->assertEquals($expected, StringHelper::fixUnbalancedInternalFormatting($text, $tags));
110+
$this->assertEquals($expectedTags, $tags);
111+
}
112+
113+
public function unbalancedInternalFormattingDataProvider(): array
101114
{
102-
$this->assertEquals('\\iThis is \\bformatted text\\I with \\Bspecial characters\\i.\\I', StringHelper::fixUnbalancedInternalFormatting('\\iThis is \\bformatted text\\I with \\Bspecial characters\\i.'));
103-
$this->assertEquals('', StringHelper::fixUnbalancedInternalFormatting(''));
104-
$this->assertEquals('456789i', StringHelper::fixUnbalancedInternalFormatting('456789i'));
105-
$this->assertEquals('\\i456789\\I', StringHelper::fixUnbalancedInternalFormatting('456789\\I'));
106-
$this->assertEquals('\\u456789\\U', StringHelper::fixUnbalancedInternalFormatting('\\u456789'));
107-
$this->assertEquals('\\i\\d\\u\\D\\\\I\\b\\B\\U', StringHelper::fixUnbalancedInternalFormatting('\\u\\D\\\\I\\b'));
115+
return [
116+
[
117+
'\\iThis is \\bformatted text\\I with \\Bspecial characters\\i.',
118+
'\\iThis is \\bformatted text\\I with \\Bspecial characters\\i.\\I',
119+
['i' => 1, 'b' => 0],
120+
],
121+
[
122+
'',
123+
'',
124+
[],
125+
],
126+
[
127+
'456789i',
128+
'456789i',
129+
[],
130+
],
131+
[
132+
'456789\\I',
133+
'\\i456789\\I',
134+
['i' => -1],
135+
],
136+
[
137+
'\\u456789',
138+
'\\u456789\\U',
139+
['u' => 1],
140+
],
141+
[
142+
'\\u\\D\\\\I\\b',
143+
'\\i\\d\\u\\D\\\\I\\b\\B\\U',
144+
['i' => -1, 'd' => -1, 'u' => 1, 'b' => 1],
145+
],
146+
];
108147
}
109148
}

0 commit comments

Comments
 (0)