3

I'm using '/\s+/' switch in preg_replace to remove all the white spaces from Javascript code, that I pass in PHP array:

preg_replace('/\s+/', '',
("
    function(uploader)
    {
        if(uploader.files.length > 1)
        {
            uploader.files.splice(1, uploader.files.length);

            apprise('You can not update more than one file at once!', {});
        }
    }
"))

This is for an very basic Javascript minification. In PHP file (source) I can have fully readable function code, while in browser, it page body it ends up like single-line string:

function(uploader,files){console.log('[PluploadUploadComplete]');console.log(files);},'QueueChanged':function(uploader){if(uploader.files.length>1){uploader.files.splice(1,uploader.files.length);apprise('Youcannotupdatemorethanonefileatonce!',{});}}

As you can see (or expect) this does affects strings in quotation marks and produce message without spaces (like: Youcannotupdatemorethanonefileatonce!).

Is there a workaround for this problem? Can I remove all whitespaces from everywhere in my string, except for part embedded in single quotation marks?

trejder
  • 15,841
  • 23
  • 110
  • 207
  • 3
    Why write yet another JS minifier? :) – ThiefMaster Jun 06 '14 at 06:54
  • FYI, added explanation. – zx81 Jun 06 '14 at 07:05
  • 1
    @ThiefMaster What made you think that? :] I'm using Yii with Plupload widget and I'm passing Plupload's events as PHP arrays. I want Javascript code passed in these arrays to be clearly readable in my Yii application (PHP code), while I want it to be minified in page, where Yii injects it. It has nothing to do with writing own, another minifier. – trejder Jun 06 '14 at 07:07
  • I need to warn others, that while answers given to this question are correct and does their job (removes white spaces from everywhere except quotation marks), they'll not satisfy story behind (outlined above). This is because, such code will also remove space from construction like `var variable` making JS code invalid. So, while answers are still correct, for the purpose, for which I asked this question, you need to consider real minificator for PHP, like [JSMin](https://code.google.com/p/minify/source/browse/min/lib/JSMin.php) for example. – trejder Jun 06 '14 at 09:16

2 Answers2

3

To match space characters except within single quotes, use this:

$regex = "~'[^']*'(*SKIP)(*F)|\s+~";

You can pop that straight into your preg_replace().

For instance: $replaced = preg_replace($regex,"",$input);

Option 2: Multiple Kinds of Quotes

If you may have single or double quotes, use this:

$regex = "~(['"]).*?\1(*SKIP)(*F)|\s+~";

How Does this Work?

On the left side of the | alternation, we match full "quoted strings", then deliberately fail, and skip to the next position in the string. On the right side, we match any whitespace, and we know it is the right whitespace because it was not matched by the expression on the left.

Reference

How to match (or replace) a pattern except in situations s1, s2, s3...

Community
  • 1
  • 1
zx81
  • 38,175
  • 8
  • 76
  • 97
  • **Perfect** answer! Thanks you so much! – trejder Jun 06 '14 at 07:02
  • @trejder You're very welcome, glat it works! If it's `perfect`, please remember to accept it. :) – zx81 Jun 06 '14 at 07:03
  • I _never_ forget about accepting answers, I found useful! :] Only I have to fight with nasty boxes saying something like `You can accept this answer within 3 seconds`! :] Oh, by the way, if we're talking about rules -- don't forget to upvote question, you find so interesting, that you're willing to spare your time to answer it! :] This is another unspoken SE rule, that (too) many forgets about, which results in most of my answered questions being 0-scored (I'm soooou sad!) :] – trejder Jun 06 '14 at 07:12
  • @trejder In your spare time you may want to have a look at the question referenced in the answer, one of my favorite techniques. :) – zx81 Jun 06 '14 at 07:14
  • Gosh, did I really wrote "thanks you"? God, where's my coffee, I need it! :] And that nasty SE-four-minute-limit-for-editing-comments stroked me again! :] – trejder Jun 06 '14 at 07:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/55175/discussion-between-zx81-and-trejder). – zx81 Jun 06 '14 at 07:18
2

You could simply capture the single quoted strings and reference it in your replacement. Be aware this will only work for a simple case of single quoted strings, not nested...

$code = preg_replace("/('[^']*')|\s+/", '$1', $code);
hwnd
  • 65,661
  • 4
  • 77
  • 114
  • _zx81_'s answer with `$regex = "~'[^']*'(*SKIP)(*F)|\s+~"` + `preg_replace($regex,...` works like a charm for me. When I replace it with yours `preg_replace("/('[^']*')|\s+/",`, I'm getting `Uncaught SyntaxError: Unexpected token ,` error in my console and entire Plupload widgets is not loading. What am I missing? – trejder Jun 06 '14 at 07:10
  • No, I don't think so, since I'm testing your solution on the same code as example give in question. I have entire code in double quotes and only one string message inside, in single quotes. Anyway, since case is solved (with _zx81_'s answer), I think, we may pass on this problem. – trejder Jun 06 '14 at 07:40