Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace hard-coded character remapping with new post-processing fix #184

Merged
merged 3 commits into from
Jun 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/class-php-typography.php
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ private function process_textnodes_internal( \DOMDocument $dom, \DOMNode $body_n

// Replace original node (if anything was changed).
if ( $new !== $original ) {
$this->replace_node_with_html( $textnode, $settings->apply_character_mapping( $new ) );
$this->replace_node_with_html( $textnode, $new );
}
}
}
Expand Down
38 changes: 9 additions & 29 deletions src/class-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
* - `$unicode_mapping`
*
* Additional removed methods:
* - `apply_character_mapping`
* - `array_map_assoc` (previously deprecated)
* - custom_unit
* - dash_style
Expand Down Expand Up @@ -133,6 +134,9 @@
* @property-read bool $ignore_parser_errors Whether lenient parser error handling (output "best guess" HTML) is enabled.
* @property-read ?callable $parser_errors_handler An optional handler for parser errors. The callable takes an array of error strings as its parameter.
*
* Post-processing:
* @property-read array<string,string> $unicode_character_mapping The Unicode character mapping (as some characters still have compatibility issues).
*
* Setters for general attributes:
* @method void set_classes_to_ignore( string[] $classes = ['vcard','noTypo'] ) Sets classes for which the typography of their children will be left untouched.
* @method void set_ids_to_ignore( string[] $ids = [] ) Sets IDs for which the typography of their children will be left untouched.
Expand Down Expand Up @@ -262,7 +266,7 @@ class Settings {
const PARSER_ERRORS_IGNORE = 'parserErrorsIgnore';
const PARSER_ERRORS_HANDLER = 'parserErrorsHandler';

// Unicode character remapping (some characters still have compatibility issues).
// Post-processing.
const UNICODE_CHARACTER_MAPPING = 'unicodeCharacterMapping';

/**
Expand Down Expand Up @@ -596,6 +600,10 @@ class Settings {
'default' => true,
'verify' => 'is_bool',
],
[
'property' => self::UNICODE_CHARACTER_MAPPING,
'name' => 'unicode_character_mapping',
],
];

/**
Expand Down Expand Up @@ -759,34 +767,6 @@ public function remap_character( string $char, string $new_char ): void {
}
}

/**
* Remaps one or more strings.
*
* @since 6.5.0
*
* @template T of string|string[]
*
* @param T $input The input string(s).
*
* @return T
*/
public function apply_character_mapping( $input ) {

// Nothing for us to do.
if ( empty( $input ) || empty( $this->data[ self::UNICODE_CHARACTER_MAPPING ] ) ) {
return $input;
}

$native_array = \is_array( $input );
$data = (array) $input;

foreach ( $data as $key => $string ) {
$data[ $key ] = \strtr( $string, $this->data[ self::UNICODE_CHARACTER_MAPPING ] );
}

return $native_array ? $data : $data[0]; // @phpstan-ignore-line -- Ignore generics/array clash
}

/**
* (Re)set various options to their default values.
*/
Expand Down
12 changes: 8 additions & 4 deletions src/fixes/class-default-registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ function ( $index ) use ( $css_classes ) {
/**
* Also register the token fixes.
*
* @var Token_Fix $fix A token fix class.
* @var class-string<Token_Fix> $fix A token fix class.
*/
foreach ( self::get_default_token_fixes() as $fix => $params ) {
$arguments = [];
Expand All @@ -128,7 +128,7 @@ function ( $index ) use ( $css_classes ) {
* }
* }
*/
protected static function get_default_node_fixes() {
protected static function get_default_node_fixes(): array {
return [
self::CHARACTERS => [
// Nodify anything that requires adjacent text awareness here.
Expand Down Expand Up @@ -188,15 +188,19 @@ protected static function get_default_node_fixes() {
'classes' => [ 'push-single', 'push-double', 'pull-single', 'pull-double' ],
],
],

self::POST_PROCESSING => [
Node_Fixes\Unicode_Remapping_Fix::class => [],
],
];
}

/**
* Returns a configuration array for the default token fixes.
*
* @return array<class-string,mixed[]>
* @return array<class-string<Token_Fix>,mixed[]>
*/
protected static function get_default_token_fixes() {
protected static function get_default_token_fixes(): array {
return [
Token_Fixes\Wrap_Hard_Hyphens_Fix::class => [],
Token_Fixes\Smart_Dashes_Hyphen_Fix::class => [],
Expand Down
8 changes: 6 additions & 2 deletions src/fixes/class-registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,29 @@
*/
class Registry {

const PRE_PROCESSING = 01;
const CHARACTERS = 10;
const SPACING_PRE_WORDS = 20;
const PROCESS_WORDS = 30;
const SPACING_POST_WORDS = 40;
const HTML_INSERTION = 50;
const POST_PROCESSING = 99;

const GROUPS = [ self::CHARACTERS, self::SPACING_PRE_WORDS, self::PROCESS_WORDS, self::SPACING_POST_WORDS, self::HTML_INSERTION ];
const GROUPS = [ self::PRE_PROCESSING, self::CHARACTERS, self::SPACING_PRE_WORDS, self::PROCESS_WORDS, self::SPACING_POST_WORDS, self::HTML_INSERTION, self::POST_PROCESSING ];

/**
* An array of Node_Fix implementations indexed by groups.
*
* @var array<int,Node_Fix[]>
*/
private $node_fixes = [
self::PRE_PROCESSING => [],
self::CHARACTERS => [],
self::SPACING_PRE_WORDS => [],
self::PROCESS_WORDS => [],
self::SPACING_POST_WORDS => [],
self::HTML_INSERTION => [],
self::POST_PROCESSING => [],
];

/**
Expand All @@ -85,7 +89,7 @@ public function __construct() {
*
* @return Node_Fix[][]
*/
public function get_node_fixes() {
public function get_node_fixes(): array {
return $this->node_fixes;
}

Expand Down
63 changes: 63 additions & 0 deletions src/fixes/node-fixes/class-unicode-remapping-fix.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php
/**
* This file is part of PHP-Typography.
*
* Copyright 2024 Peter Putzer.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***
*
* @package mundschenk-at/php-typography
* @license http://www.gnu.org/licenses/gpl-2.0.html
*/

namespace PHP_Typography\Fixes\Node_Fixes;

use PHP_Typography\Settings;

/**
* Remaps Unicode characters.
*
* @author Peter Putzer <github@mundschenk.at>
*
* @since 7.0.0
*/
class Unicode_Remapping_Fix extends Abstract_Node_Fix {

/**
* Creates a new node fix.
*/
public function __construct() {
parent::__construct( true );
}

/**
* Apply the fix to a given textnode.
*
* @param \DOMText $textnode The DOM node.
* @param Settings $settings The settings to apply.
* @param bool $is_title Indicates if the processed tokens occur in a title/heading context.
*
* @return void
*/
public function apply( \DOMText $textnode, Settings $settings, $is_title ) {
if ( empty( $settings->unicode_character_mapping ) ) {
return;
}

$textnode->data = \strtr( $textnode->data, $settings->unicode_character_mapping );
}
}
1 change: 1 addition & 0 deletions tests/class-php-typography-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
* @uses PHP_Typography\Fixes\Node_Fixes\Style_Ampersands_Fix
* @uses PHP_Typography\Fixes\Node_Fixes\Style_Caps_Fix
* @uses PHP_Typography\Fixes\Node_Fixes\Style_Numbers_Fix
* @uses PHP_Typography\Fixes\Node_Fixes\Unicode_Remapping_Fix
* @uses PHP_Typography\Fixes\Node_Fixes\Unit_Spacing_Fix
*/
class PHP_Typography_Test extends Testcase {
Expand Down
36 changes: 0 additions & 36 deletions tests/class-settings-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -1508,40 +1508,4 @@ public function test_remap_character() {
$this->assertCount( 2, $data[ Settings::UNICODE_CHARACTER_MAPPING ] );
$this->assertContains( 'x', $data[ Settings::UNICODE_CHARACTER_MAPPING ] );
}


/**
* Provides data for testing apply_character_mapping.
*
* @return array
*/
public function provide_apply_character_mapping_data() {
return [
[ 'foobar', 'foobAz' ],
[ [ 'foobar' ], [ 'foobAz' ] ],
[ [ 'foobar', 'fugazi' ], [ 'foobAz', 'fugAzi' ] ],
[ '', '' ],
];
}

/**
* Tests apply_character_mapping.
*
* @covers ::apply_character_mapping
*
* @dataProvider provide_apply_character_mapping_data
*
* @param string|string[] $input The input.
* @param string|string[] $result The expected result.
*/
public function test_apply_character_mapping( $input, $result ) {
$mapping = [
'a' => 'A',
'r' => 'z',
];

$s = new Settings( false, $mapping );

$this->assertSame( $result, $s->apply_character_mapping( $input ) );
}
}
121 changes: 121 additions & 0 deletions tests/fixes/node-fixes/class-unicode-remapping-fix-test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php
/**
* This file is part of PHP-Typography.
*
* Copyright 2024 Peter Putzer.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* of the License, or ( at your option ) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @package mundschenk-at/php-typography/tests
* @license http://www.gnu.org/licenses/gpl-2.0.html
*/

namespace PHP_Typography\Tests\Fixes\Node_Fixes;

use PHP_Typography\Fixes\Node_Fixes;
use PHP_Typography\Settings;

/**
* Unicode_Remapping_Fix unit test.
*
* @coversDefaultClass \PHP_Typography\Fixes\Node_Fixes\Unicode_Remapping_Fix
* @usesDefaultClass \PHP_Typography\Fixes\Node_Fixes\Unicode_Remapping_Fix
*
* @uses ::__construct
* @uses PHP_Typography\Fixes\Node_Fixes\Abstract_Node_Fix::__construct
* @uses PHP_Typography\DOM
* @uses PHP_Typography\Settings
* @uses PHP_Typography\Settings\Dash_Style
* @uses PHP_Typography\Settings\Quote_Style
* @uses PHP_Typography\Settings\Simple_Dashes
* @uses PHP_Typography\Settings\Simple_Quotes
* @uses PHP_Typography\Strings
*/
class Unicode_Remapping_Fix_Test extends Node_Fix_Testcase {

/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*/
protected function set_up() {
parent::set_up();

$this->fix = new Node_Fixes\Unicode_Remapping_Fix();
}

/**
* Provides data for testing apply.
*
* @return array
*/
public function provide_character_mapping_data() {
return [
[
'foobar',
[
'a' => 'A',
'r' => 'z',
],
'foobAz',
],
[
'',
[
'a' => 'A',
'r' => 'z',
],
'',
],
];
}

/**
* Test apply.
*
* @covers ::apply
* @covers ::__construct
*
* @uses PHP_Typography\Fixes\Node_Fixes\Simple_Regex_Replacement_Fix::apply
*
* @dataProvider provide_character_mapping_data
*
* @param string $input HTML input.
* @param string[] $mapping The character remapping to apply.
* @param string $result Expected result.
*/
public function test_apply( $input, array $mapping, $result ) {
$this->s = new Settings( false, $mapping );

$this->assertFixResultSame( $input, $result );
}

/**
* Test apply.
*
* @covers ::apply
* @covers ::__construct
*
* @uses PHP_Typography\Fixes\Node_Fixes\Simple_Regex_Replacement_Fix::apply
*
* @dataProvider provide_character_mapping_data
*
* @param string $input HTML input.
*/
public function test_apply_off( $input ) {
$this->s = new Settings( false, [] );

$this->assertFixResultSame( $input, $input );
}
}