2

I am trying to parse a media query with Javascript.

I intend the mark-up string to look like this

@media not screen and (min-width: 700px) {
    padding-left: 30px;
    background: url(email-icon.png) left center no-repeat;
}
@media (max-width: 600px) {  
   color: red; 
}

Will an output:

@media not screen and (min-width: 700px) {
    .foo{
        padding-left: 30px;
        background: url(email-icon.png) left center no-repeat;
    }
}
@media (max-width: 600px) { 
   .foo{ 
      color: red; 
   }
}

So far I have this

const css =  `@media (max-width: 600px) {   color: red;    }`
const pattern = new RegExp('@media[^{]+([\s\S]+})\s*')

const cssnew = css.replace( pattern, (full,match) => `{ .foo${match}}` );
//   cssnew === "@media (max-width: 600px) {  .foo{ color: red;  }  }"

This Regex look like it working for 1(@media) https://regex101.com/r/r0sWeu/1 and thats ok... but the replace function is not getting called?

Thanks for an help

Brian
  • 1,026
  • 1
  • 15
  • 25
  • it doesn't work for `cssnew` value https://regex101.com/r/iT2eR5/17 – marzelin Jul 22 '17 at 10:07
  • Sorry the link was using an old regx It works using `@media[^{]+([\s\S]+})\s*` TRY: https://regex101.com/r/r0sWeu/1 – Brian Jul 22 '17 at 10:32
  • `cssnew = cssnew.replace(/@media[^{]+([\s\S]+})\s*/g, '{ .foo $1}')`. You made several very common mistakes here. – Wiktor Stribiżew Jul 22 '17 at 10:56
  • Strings are immutable, meaning you can't modify an existing string, you can only create a new string with the modifications. The `replace()` function returns this new modified string but you're not doing anything with it. – Lennholm Jul 22 '17 at 10:57

2 Answers2

0

Backslashes are escape characters in strings as well. Change '@media[^{]+([\s\S]+})\s*' to '@media[^{]+([\\s\\S]+})\\s*'

marzelin
  • 10,790
  • 2
  • 30
  • 49
  • Thanks, but It don't match the example output in the question. How would I get `@media (max-width: 600px) { .foo { color: red; } }`? – Brian Jul 22 '17 at 20:46
0

You need to fix the code as follows:

const cssnew =  ` @media (max-width: 600px) {   color: red;    }`
const pattern = /(@media[^{]+{\s*)([\s\S]+?)(\s*})/g

console.log(cssnew.replace( pattern, "$1.foo{\n\t\t$2\n\t}$3" ));

Notes:

  • Inside regex constructors, backslash is used to form escape sequences, and to define a literal backslash, it must be doubled. It is easier to go with a regex literal, /pattern/, where you do not need to double the backslashes
  • The new value should be assigned to a variable you want to modify as strings are immutable in JS
  • There is no need to use a callback inside a replace method if you just want to use a capturing group value, just use backreference $1 that will get the value stored in Group 1.
  • Also, the [\s\S]+ is too greedy, to get up to the first }, use a lazy version, [\s\S]+?.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Thanks, but It don't match the example output in the question. How would I get `@media (max-width: 600px) { .foo { color: red; } }`? – Brian Jul 22 '17 at 20:45
  • 1
    You cannot match nested chars with JS regex. You need to build a parsing code. Do you need to match everything from `@media` and the next `{` up to the next matching `}`? – Wiktor Stribiżew Jul 22 '17 at 20:59
  • Do you need to match everything from @media and the next { up to the next matching }? Yes! – Brian Jul 22 '17 at 21:08
  • @codemeasandwich: Could you please still confirm which text you try to match: 1) https://regex101.com/r/oq9QJp/1 and 2) https://regex101.com/r/oq9QJp/2 (these are not solutions, just need clarification what text you need to analyze). – Wiktor Stribiżew Jul 22 '17 at 21:25
  • 1 - I want to inject/wrap with a class(or css select) – Brian Jul 22 '17 at 21:35
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/149919/discussion-between-codemeasandwich-and-wiktor-stribizew). – Brian Jul 23 '17 at 08:17
  • 1
    @codemeasandwich Try `cssnew.replace( pattern, "$1.foo{\n\t\t$2\n\t}$3" );` with `/(@media[^{]+{\s*)([\s\S]+?)(\s*})/g` pattern. – Wiktor Stribiżew Jul 23 '17 at 09:39
  • Yes. that work https://jsfiddle.net/codemeasandwich/w6gg8ycm/ Please update you answer's code example with this and I can mark it as correct :) Big thanks for you help on this! – Brian Jul 23 '17 at 10:43