Ori.livneh has uploaded a new change for review. https://gerrit.wikimedia.org/r/227365
Change subject: Initial commit. ...................................................................... Initial commit. Change-Id: I6330ca5e3f83534dab0980c8a8527adac1b7c4ea --- A .editorconfig A .gitignore A .jshintrc A .travis.yml A Doxyfile A LICENSE A README.md A composer.json A phpcs.xml A phpunit.xml.dist A src/WrappedString.php A tests/WrappedStringTest.php 12 files changed, 363 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/WrappedString refs/changes/65/227365/1 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..42aefb6 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = tab + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c760786 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/coverage +/doc +/vendor +/composer.lock diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..0cc2a4a --- /dev/null +++ b/.jshintrc @@ -0,0 +1,12 @@ +{ + // Enforcing + "bitwise": true, + "eqeqeq": true, + "freeze": true, + "latedef": true, + "noarg": true, + "nonew": true, + "undef": true, + "unused": true, + "node": true +} diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c25a516 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +sudo: false +language: php +php: + - "5.3.3" + - "5.3" + - "5.4" + - "5.5" + - "5.6" + - "hhvm" +install: + - composer install +script: + - composer test diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..3aec825 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,26 @@ +# Doxyfile for WrappedString +# +# See <http://www.stack.nl/~dimitri/doxygen/manual/config.html> +# for help on how to use this file to configure Doxygen. + +PROJECT_NAME = "WrappedString" +PROJECT_BRIEF = "Automatically compact sequentially-outputted strings that share a common prefix / suffix pair." +OUTPUT_DIRECTORY = doc +JAVADOC_AUTOBRIEF = YES +QT_AUTOBRIEF = YES +WARN_NO_PARAMDOC = YES +INPUT = README.md src/ +FILE_PATTERNS = *.php +RECURSIVE = YES +USE_MDFILE_AS_MAINPAGE = README.md +HTML_DYNAMIC_SECTIONS = YES +GENERATE_TREEVIEW = YES +TREEVIEW_WIDTH = 250 +GENERATE_LATEX = NO +HAVE_DOT = YES +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +TEMPLATE_RELATIONS = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +DOT_MULTI_TARGETS = YES diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9c1052f --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 Timo Tijhof <t...@wikimedia.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..06b5c1d --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +WrappedString +============= + +WrappedString is a small PHP library for compacting redundant string-wrapping +code in text output. The most common use-case is to eliminate redundant runs of +HTML open/close tags. + +Here is how you use it: + +```php +use WrappedString\MultiStringMatcher; + +$buffer = array(); +$buffer[] = new WrappedString( '<script>var q = q || [];', 'q.push( 0 );', '</script>' ); +$buffer[] = new WrappedString( '<script>var q = q || [];', 'q.push( 1 );', '</script>' ); +$output = WrappedString::join( "\n", $buffer ); +// Result: <script>var q = q || [];q.push( 0 );q.push( 1 );</script> + +``` + +License +------- + +The project is licensed under the MIT license. diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..022db90 --- /dev/null +++ b/composer.json @@ -0,0 +1,30 @@ +{ + "name": "mediawiki/wrappedstring", + "description": "Automatically compact sequentially-outputted strings that share a common prefix / suffix pair.", + "license": "MIT", + "homepage": "https://www.mediawiki.org/wiki/WrappedString", + "authors": [ + { + "name": "Timo Tijhof", + "email": "t...@wikimedia.org" + } + ], + "autoload": { + "classmap": ["src/"] + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "jakub-onderka/php-parallel-lint": "^0.9.0.0", + "phpunit/phpunit": "^4.7.7.0", + "mediawiki/mediawiki-codesniffer": "^0.3.0.0" + }, + "scripts": { + "test": [ + "parallel-lint . --exclude vendor", + "phpunit $PHPUNIT_ARGS", + "phpcs -p" + ] + } +} diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..a55f518 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<ruleset> + <rule ref="vendor/mediawiki/mediawiki-codesniffer/MediaWiki"/> + + <file>.</file> + <arg name="encoding" value="UTF-8"/> + <arg name="extensions" value="php"/> + <exclude-pattern>coverage</exclude-pattern> + <exclude-pattern>vendor</exclude-pattern> + <exclude-pattern>doc/html</exclude-pattern> +</ruleset> diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..265197f --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,14 @@ +<phpunit colors="true" + beStrictAboutTestsThatDoNotTestAnything="true" + beStrictAboutOutputDuringTests="true"> + <testsuites> + <testsuite name="WrappedString Tests"> + <directory>./tests</directory> + </testsuite> + </testsuites> + <filter> + <whitelist addUncoveredFilesFromWhitelist="true"> + <directory suffix=".php">./src</directory> + </whitelist> + </filter> +</phpunit> diff --git a/src/WrappedString.php b/src/WrappedString.php new file mode 100644 index 0000000..e8669ef --- /dev/null +++ b/src/WrappedString.php @@ -0,0 +1,101 @@ +<?php +/** + * Copyright (c) 2015 Timo Tijhof <t...@wikimedia.org> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * @file + * @author Timo Tijhof <t...@wikimedia.org> + */ + +namespace WrappedString; + +class WrappedString { + /** @var string */ + protected $before; + + /** @var string */ + protected $content; + + /** @var string */ + protected $after; + + /** + * @param string $before + * @param string $content + * @param string $after + */ + public function __construct( $before, $content = '', $after = '' ) { + $this->before = $before; + $this->content = $content; + $this->after = $after; + } + + /** + * @param string $content + * @return WrappedString Newly wrapped string + */ + protected function extend( $content ) { + $wrap = clone $this; + $wrap->content .= $content; + return $wrap; + } + + /** + * Merge consecutive wrapped strings with the same before/after values. + * + * Does not modify the array or the WrappedString objects. + * + * @param WrappedString[] $wraps + * @return WrappedString[] + */ + protected static function compact( Array &$wraps ) { + $consolidated = array(); + $prev = current( $wraps ); + while ( ( $wrap = next( $wraps ) ) !== false ) { + if ( $prev->before === $wrap->before && $prev->after === $wrap->after ) { + $prev = $prev->extend( $wrap->content ); + } else { + $consolidated[] = $prev; + $prev = $wrap; + } + } + // Add last one + $consolidated[] = $prev; + + return $consolidated; + } + + /** + * Join a several wrapped strings with a separator between each. + * + * @param string $sep + * @param WrappedString[] $wraps + * @return string + */ + public static function join( $sep, Array $wraps ) { + return implode( $sep, self::compact( $wraps ) ); + } + + /** @return string */ + public function __toString() { + return $this->before . $this->content . $this->after; + } +} diff --git a/tests/WrappedStringTest.php b/tests/WrappedStringTest.php new file mode 100644 index 0000000..d7cbcaa --- /dev/null +++ b/tests/WrappedStringTest.php @@ -0,0 +1,103 @@ +<?php +/** + * Copyright (c) 2015 Timo Tijhof <t...@wikimedia.org> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * @file + * @author Timo Tijhof <t...@wikimedia.org> + */ + +namespace WrappedString\Test; + +use WrappedString\WrappedString; + +/** + * @covers WrappedString\WrappedString + */ +class WrappedStringTest extends \PHPUnit_Framework_TestCase { + + public static function provideCompact() { + return array( + array( + 'Merge consecutive strings that have the same before/after values', + array( + new WrappedString( '<foo>var q = q || [];', 'q.push( 0 );', '</foo>' ), + new WrappedString( '<foo>var q = q || [];', 'q.push( 1 );', '</foo>' ), + new WrappedString( '<foo>var q = q || [];', 'q.push( 2 );', '</foo>' ), + ), + '<foo>var q = q || [];q.push( 0 );q.push( 1 );q.push( 2 );</foo>', + ), + array( + 'Consecutive strings that look similar but have different dividers are not merged', + array( + new WrappedString( '<foo>var q = q || [];', 'q.push( 0 );', '</foo>' ), + new WrappedString( '<foo>var q = q || [];', 'q.push( 1 );', '</foo>' ), + new WrappedString( '<foo>', 'var q = q || [];q.push( 2 );', '</foo>' ), + new WrappedString( '<foo>var q = q || [];', 'q.push( 3 );', '</foo>' ), + ), + '<foo>var q = q || [];q.push( 0 );q.push( 1 );</foo>' . "\n" . + '<foo>var q = q || [];q.push( 2 );</foo>' . "\n" . + '<foo>var q = q || [];q.push( 3 );</foo>', + ), + array( + 'Merge consecutive string that have an empty string prefix', + array( + new WrappedString( '<foo>var q = q || [];', 'q.push( 0 );', '</foo>' ), + new WrappedString( '', '<foo special=a></foo>' ), + new WrappedString( '', '<foo special=b></foo>' ), + new WrappedString( '<foo special=c></foo>' ), + new WrappedString( '<foo>var q = q || [];', 'q.push( 1 );', '</foo>' ), + ), + '<foo>var q = q || [];q.push( 0 );</foo>' . "\n" . + '<foo special=a></foo><foo special=b></foo>' . "\n" . + '<foo special=c></foo>' . "\n" . + '<foo>var q = q || [];q.push( 1 );</foo>', + ), + array( + 'No merges when there are no consecutive strings with matching segments', + array( + new WrappedString( '<foo>var q = q || [];', 'q.push( 0 );', '</foo>' ), + new WrappedString( '', '<foo special=a></foo>' ), + new WrappedString( '<foo>var q = q || [];', 'q.push( 1 );', '</foo>' ), + new WrappedString( '', '<foo special=b></foo>' ), + new WrappedString( '<foo>var q = q || [];', 'q.push( 2 );', '</foo>' ), + ), + '<foo>var q = q || [];q.push( 0 );</foo>' . "\n" . + '<foo special=a></foo>' . "\n" . + '<foo>var q = q || [];q.push( 1 );</foo>' . "\n" . + '<foo special=b></foo>' . "\n" . + '<foo>var q = q || [];q.push( 2 );</foo>', + ), + ); + } + + /** + * @covers WrappedString + * @dataProvider provideCompact + */ + public function testCompact( $msg, $wraps, $expected ) { + $this->assertEquals( + $expected, + WrappedString::join( "\n", $wraps ), + $msg + ); + } +} -- To view, visit https://gerrit.wikimedia.org/r/227365 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I6330ca5e3f83534dab0980c8a8527adac1b7c4ea Gerrit-PatchSet: 1 Gerrit-Project: WrappedString Gerrit-Branch: master Gerrit-Owner: Ori.livneh <o...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits