17

I need to modify the following javascript regex because the negative lookbehind in it throws an error in firefox:

content = content.replace(/(?![^<]*>)(?:[\"])([^"]*?)(?<!=)(?:[\"])(?!>)/g, '„$1“');

Does anyone have an idea and can help me out?

mplungjan
  • 169,008
  • 28
  • 173
  • 236
Cla
  • 303
  • 1
  • 3
  • 11
  • You just can move the `=` to the negated character class, `/(?![^<]>)"([^"=]?)"(?!>)/g` – Wiktor Stribiżew Apr 24 '18 at 22:47
  • 1
    Please vote for the issue in firefox at https://bugzilla.mozilla.org/show_bug.cgi?id=1225665 – bradlis7 Jun 06 '19 at 16:30
  • @bradlis7 How do you vote? (It is quite a while since I logged in to bugzilla, but I still don't see a vote button. I did start following it - is that the same thing?) And this seems one of the few things that there is no shim for. – Darren Cook Sep 06 '19 at 12:32
  • 2
    @DarrenCook After logging in, in the "Details Panel", It says "27 Votes [Vote]". It's a clunky UI, as you have to go to your vote page, check the issue and then submit. – bradlis7 Sep 09 '19 at 19:06
  • Perhaps real soon now: https://bugzilla.mozilla.org/show_bug.cgi?id=1634135 – mplungjan May 29 '20 at 07:18

4 Answers4

28

July 1, 2020 Update

Starting with the FireFox 78 version, RegExp finally supports lookbehinds, dotAll s flag, Unicode escape sequences and named captures, see the Release Notes:

New RegExp engine in SpiderMonkey, adding support for the dotAll flag, Unicode escape sequences, lookbehind references, and named captures.

Thank you very much, FireFox developers!!!


Lookbehinds are only available in browsers supporting ECMA2018 standard, and that means, only the latest versions of Chrome can handle them.

To support the majority of browsers, convert your pattern to only use lookaheads.

The (?<!=) negative lookbehind makes sure there is no = immediately to the left of the current location. [^"] is the atom that matches that character (note that ? quantifier makes it optional, but " that is before [^"] can't be = and there is no need restricting that position).

So, you may use

content = content.replace(/(?![^<]>)"([^"=]?)"(?!>)/g, '„$1"');
                                      ^^^^^

Note that (?:[\"]) is equal to ". [^"=]? matches 1 or 0 occurrences of a char other than " and =.

See the regex demo.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
2

Lookbehind assertions are part of ES2018. They are not yet supported by firefox, that's why you're getting an error.

Chrome supports them since version 62, and you can use them in Node.js >= 6.4 with the harmony flag, or in >= 9 without any flag.

You can check the proposal here & browser support here

Marcos Casagrande
  • 37,983
  • 8
  • 84
  • 98
2

The exact equivalent of your regex (?![^<]*>)"([^"]*?)(?<!=)"(?!>)

without the lookbehind assertion is:

(?![^<]*>)"((?:[^"=]+|=(?!"))*)"(?!>)

Readable version

 (?! [^<]* > )
 "
 (                             # (1 start)
      (?:
           [^"=]+ 
        |  
           = 
           (?! " )
      )*
 )                             # (1 end)
 "
 (?! > )

Note this is not like your chosen answer, which is not an equivalent .

Eugene Barsky
  • 5,780
  • 3
  • 17
  • 40
1

2 years later, Firefox is finally catching up. ES2018 RegExp features will be included in FF78, due to be released end of June, 2020: https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/78#JavaScript

jaynetics
  • 1,234
  • 12
  • 15