Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the differences between client-side and server-side handling of relative urls and imports #961

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/less/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ function loadStyleSheet(sheet, callback, reload, remaining) {
href = url.slice(0, url.lastIndexOf('/') + 1) + href;
}
}

var rootpath = sheet.rootpath || href.replace(/[\w\.-]+$/, '');

xhr(sheet.href, sheet.type, function (data, lastModified) {
if (!reload && styles && lastModified &&
(new(Date)(lastModified).valueOf() ===
Expand All @@ -149,6 +152,7 @@ function loadStyleSheet(sheet, callback, reload, remaining) {
paths: [href.replace(/[\w\.-]+$/, '')],
mime: sheet.type,
filename: href,
rootpath: rootpath, // Passing top importing sheet ref down.
'contents': contents // Passing top importing parser content cache ref down.
}).parse(data, function (e, root) {
if (e) { return error(e, href) }
Expand Down
7 changes: 4 additions & 3 deletions lib/less/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ less.Parser = function Parser(env) {
queue: [], // Files which haven't been imported yet
files: {}, // Holds the imported parse trees
contents: env.contents, // Holds the imported file contents
rootpath: env.rootpath, // Holds the path of the top importing sheet
mime: env && env.mime, // MIME type of .less files
error: null, // Error in parsing/evaluating an import
push: function (path, callback) {
Expand Down Expand Up @@ -647,7 +648,7 @@ less.Parser = function Parser(env) {
expect(')');

return new(tree.URL)((value.value != null || value instanceof tree.Variable)
? value : new(tree.Anonymous)(value), imports.paths);
? value : new(tree.Anonymous)(value), env.rootpath);
},

//
Expand Down Expand Up @@ -1120,7 +1121,7 @@ less.Parser = function Parser(env) {
if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) {
features = $(this.mediaFeatures);
if ($(';')) {
return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index);
return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index, env.rootpath);
}
}

Expand Down Expand Up @@ -1407,7 +1408,7 @@ if (less.mode === 'browser' || less.mode === 'rhino') {
// This is so we can get the syntax tree as opposed to just the CSS output,
// as we need this to evaluate the current stylesheet.
// __ Now using the hack of passing a ref to top parser's content cache in the 1st arg. __
loadStyleSheet({ href: path, title: path, type: env.mime, contents: env.contents }, function (e) {
loadStyleSheet({ href: path, title: path, type: env.mime, contents: env.contents, rootpath: env.rootpath }, function (e) {
if (e && typeof(env.errback) === "function") {
env.errback.call(null, path, paths, callback, env);
} else {
Expand Down
7 changes: 6 additions & 1 deletion lib/less/tree/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
// `import,push`, we also pass it a callback, which it'll call once
// the file has been fetched, and parsed.
//
tree.Import = function (path, imports, features, once, index) {
tree.Import = function (path, imports, features, once, index, rootpath) {
var that = this;

this.once = once;
this.index = index;
this._path = path;
this.features = features && new(tree.Value)(features);
this.rootpath = rootpath

// The '.less' extension is optional
if (path instanceof tree.Quoted) {
Expand Down Expand Up @@ -52,6 +53,10 @@ tree.Import.prototype = {
var features = this.features ? ' ' + this.features.toCSS(env) : '';

if (this.css) {
// Add the base path if the import is relative and we are in the browser
if (typeof window !== 'undefined' && typeof this._path.value === "string" && !/^(?:[a-z-]+:|\/)/.test(this._path.value)) {
this._path.value = this.rootpath + this._path.value;
}
return "@import " + this._path.toCSS() + features + ';\n';
} else {
return "";
Expand Down
10 changes: 5 additions & 5 deletions lib/less/tree/url.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
(function (tree) {

tree.URL = function (val, paths) {
tree.URL = function (val, rootpath) {
this.value = val;
this.paths = paths;
this.rootpath = rootpath
};
tree.URL.prototype = {
toCSS: function () {
Expand All @@ -12,11 +12,11 @@ tree.URL.prototype = {
var val = this.value.eval(ctx);

// Add the base path if the URL is relative and we are in the browser
if (typeof window !== 'undefined' && typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value) && this.paths.length > 0) {
val.value = this.paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value);
if (typeof window !== 'undefined' && typeof val.value === "string" && !/^(?:[a-z-]+:|\/)/.test(val.value)) {
val.value = this.rootpath + val.value;
}

return new(tree.URL)(val, this.paths);
return new(tree.URL)(val, this.rootpath);
}
};

Expand Down
12 changes: 12 additions & 0 deletions test-relative-paths/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
all: clean
@echo "Building less.js:"
make -C .. min

@echo

@echo "Building test-relative-paths:"
../bin/lessc static/less/main.less static/css/main.css

clean:
@echo "Cleaning up test-relative-paths:"
rm -f static/css/main.css
Binary file added test-relative-paths/static/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test-relative-paths/static/assets/xecret.ttf
Binary file not shown.
3 changes: 3 additions & 0 deletions test-relative-paths/static/css/background.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
html {
background-color: #82e291;
}
8 changes: 8 additions & 0 deletions test-relative-paths/static/less/imports/font.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@font-face {
font-family: xecret;
src: url('../assets/xecret.ttf');
}

#secret {
font-family: xecret, sans-serif;
}
5 changes: 5 additions & 0 deletions test-relative-paths/static/less/imports/logo.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#logo {
width: 199px;
height: 81px;
background-image: url('../assets/logo.png');
}
4 changes: 4 additions & 0 deletions test-relative-paths/static/less/main.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@import "../css/background.css";

@import "imports/logo";
@import "imports/font";
26 changes: 26 additions & 0 deletions test-relative-paths/test-clientside.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8">
<title>Test case for relative paths</title>
<link rel="stylesheet/less" href="static/less/main.less">
<script>var less = { env: 'development' };</script>
<script src="../dist/less-1.3.0.js"></script>
</head>

<body>
<h1>Client-side test case for relative paths</a></h1>

<h2>Test 1: imports of .css</h2>
<p>Expected result: the background of the page should be green.</p>

<h2>Test 2: background-image url</h2>
<div id="logo"></div>
<p>Expected result: the LESS logo should appear above.</p>

<h2>Test 3: @font-face url</h2>
<div id="secret">abcdef</div>
<p>Expected result: the text above should be a series of "X".</p>
</body>
</html>
24 changes: 24 additions & 0 deletions test-relative-paths/test-serverside.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8">
<title>Test case for relative paths</title>
<link rel="stylesheet" href="static/css/main.css">
</head>

<body>
<h1>Server-side test case for relative paths</a></h1>

<h2>Test 1: imports of .css</h2>
<p>Expected result: the background of the page should be green.</p>

<h2>Test 2: background-image url</h2>
<div id="logo"></div>
<p>Expected result: the LESS logo should appear above.</p>

<h2>Test 3: @font-face url</h2>
<div id="secret">abcdef</div>
<p>Expected result: the text above should be a series of "X".</p>
</body>
</html>