wikimedia / less.php

Less.js ported to PHP. Mirrored from https://gerrit.wikimedia.org/g/mediawiki/libs/less.php/
Apache License 2.0
111 stars 195 forks source link

seperate sourcemaps are badly generated #41

Open dali-rajab opened 4 years ago

dali-rajab commented 4 years ago

Hello guys, this is my first use of less.php, so here is my exemple: The web DocumentRoot is public_html/ , which includes these files :

index.php

<?php
require __DIR__ . '/vendor/autoload.php';

$less_file = __DIR__ . '/theme.less';

$options = array(
    'sourceMap'         => true,
    'sourceMapWriteTo'  => __DIR__ . '/theme.map',
    'sourceMapURL'      => '/less_php/theme.map',
    );
$parser = new Less_Parser($options);
$parser->parseFile( $less_file , 'http://exemple.com/less_php/' );
$generated_css = $parser->getCss();

$css_file = fopen("theme.css", "w") or die("Unable to open theme.css!");
fwrite($css_file, $generated_css);
fclose($css_file);
?>

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="theme.css">
</head>
    <body>

    <div class="h1">Body .h1</div>

    <div class="btn">bouton</div>

    <footer>
        <div class="h2">footer .h2</div>
    </footer>

    </body>
</html>

theme.less

@primary-color: #990000;
@primary-font-siz: 1.8rem;

div {
  background: url('test.jpeg');
}

@import 'header';

@import 'components/buttons';

@import 'footer';

footer.less

footer {
  .h2 {
    color: @primary-color;
    font-size: @primary-font-siz;
  }
}

header.less

body {
  .h1 {
    color: @primary-color;
    font-size: @primary-font-siz;
  }
}

components/buttons.less

.btn {
  background-color: @primary-color;
  font-size: @primary-font-siz;
}

The generated theme.css

div {
  background: url('http://exemple.com/less_php/test.jpeg');
}
body .h1 {
  color: #990000;
  font-size: 1.8rem;
}
.btn {
  background-color: #990000;
  font-size: 1.8rem;
}
footer .h2 {
  color: #990000;
  font-size: 1.8rem;
}
/*# sourceMappingURL=/less_php/theme.map */

The issue

the generated theme.map looks like this

{
   "version":3,
   "sources":[
      "home\/foo\/public_html\/less_php\/theme.less",
      "home\/foo\/public_html\/less_php\/header.less",
      "home\/foo\/public_html\/less_php\/components\/buttons.less",
      "home\/foo\/public_html\/less_php\/footer.less"
   ],
   "names":[],
   "mappings":"AAGA;EACE,gBAAgB,wCAAhB;;ACHF,IACE;EACE,cAAA;EACA,iBAAA;;ACJJ;EACE,yBAAA;EACA,iBAAA;;ACDF,MACE;EACE,cAAA;EACA,iBAAA"
}

The "sources" values shouldn't be absolute, because when using the navigator inspector, the navigator can't access to them.

The fix

vendor/wikimedia/less.php/lib/Less/SourceMap/Generator.php I removed this block :

if(strpos($filename, '\\') === 0 || strpos($filename, '/') === 0){
    $filename = substr($filename, 1);
}

And I changed this line :

$this->sources[$fileInfo['currentUri']] = $fileInfo['filename'];

to become :

$this->sources[$fileInfo['currentUri']] = $fileInfo['currentUri'];

So the result of the new generated theme.map is :

{
   "version":3,
   "sources":[
      "http:\/\/exemple.com\/less_php\/theme.less",
      "http:\/\/exemple.com\/less_php\/header.less",
      "http:\/\/exemple.com\/less_php\/components\/buttons.less",
      "http:\/\/exemple.com\/less_php\/footer.less"
   ],
   "names":[],
   "mappings":"AAGA;EACE,gBAAgB,wCAAhB;;ACHF,IACE;EACE,cAAA;EACA,iBAAA;;ACJJ;EACE,yBAAA;EACA,iBAAA;;ACDF,MACE;EACE,cAAA;EACA,iBAAA"
}

And everything is ok in the navigator inspector 💯

Thank you for your help and suggestions 👍

dleffler commented 4 years ago

I can confirm the 'sources' entries are bad. On windows servers it also includes the drive letter. HOWEVER, the correct entry should only be the relative path on the web server...so the example above a correct 'sources' entry would be 'less_php\/theme.less'.

The full path is supposed to be trimmed in the Generator->normalizeFilename() function, HOWEVER the passed filename is TOO full so that the sourceMapBasepath can't be found/replaced by the strpos/substr calls.

dleffler commented 4 years ago

Since the standard is for the sources to be a relative path, the real fix is to pass a 'sourceMapBaseName' of the root part of the path which when stripped from the full path by the parser will create a relative path. In your case the correct param passed should be:

$options = array(
    'sourceMap'         => true,
    'sourceMapWriteTo'  => __DIR__ . '/theme.map',
    'sourceMapURL'      => '/less_php/theme.map',
        'sourceMapBaseName'   =>'/home/foo/public_html/',
);

The fix for my problem is to add the following lines to the Parser::AbsPath() function after the call to realpath()


$path = realpath($path);
if (!empty($path[1]) && $path[1] === ':') {
    $path = substr($path,2);
}
dali-rajab commented 4 years ago

@dleffler thank you for your reply, I hope that the maintainers will fix that soon

digitaldonkey commented 1 month ago

My quick composer patch wikimedia-sourcemaps.patch

worked for me. Maybe does not address all issues.

Index: lib/Less/SourceMap/Generator.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/lib/Less/SourceMap/Generator.php b/lib/Less/SourceMap/Generator.php
--- a/lib/Less/SourceMap/Generator.php  
+++ b/lib/Less/SourceMap/Generator.php  
@@ -206,9 +206,8 @@
            'original_column' => $originalColumn,
            'source_file' => $fileInfo['currentUri']
        ];
-
-       $this->sources[$fileInfo['currentUri']] = $fileInfo['filename'];
-   }
+    $this->sources[$fileInfo['currentUri']] = $fileInfo['currentUri'];
+  }

    /**
     * Generates the JSON source map