Skip to content

Commit 2d43c0b

Browse files
authored
Feature/rewrite urls (#3248)
* Rename relativeUrls option to rewriteUrls * Refactor contexts.js - Rename isPathRelative to pathRequiresRewrite - Add special handling for rewriteUrls=relative - Add rewritePath for path rewriting - Ensure that explicit relative paths stay explicit relative - Remove code style inconsistencies * Add missing tests for url rewriting * Rename rewrite-urls option value to explicit-relative * Add missing tests for url rewriting * Refactor rewrite urls options - Rename explicit-relative to local - Add rewrite-urls argument validation - Replace unknown CSS property background-url with background-image Based on discussion #3041 * Re-add tests for deprecated relative-urls option * Improve tests - Remove redundant tests - Add rootpath-rewrite-urls-all test - Add rootpath-rewrite-urls-local test * Fix typo in unknown argument warning * Revert old tests to deprecated relativeUrls option again * Added more CSS Grid tests * All tests passing * Merge branch 'master' into feature/rewrite-urls (#3282) * WIP - Added strictMath: 'division' option * Removes `less-rhino` (broken for a long time) - Fixes #3241 * Expressions require a delimiter of some kind in mixin args * Removes "double paren" issue for boolean / if function * WIP each() re-implementation * Allows plain conditions without parentheses * Added each() and tests * Added tests calling mixins from each() * Fixes #1880 - Adds two new math modes and deprecates strictMath * Allows named args for detached ruleset (anonymous mixin) * Makes sure this doesn't regress needing parens around mixin guard conditions * Remove javascriptEnabled from browser options check, add to defaults * Workaround weird Jasmine conversion of < to HTML entity * Removes remaining Rhino cruft * Remove rhino files from bower * Bump Jasmine version * Added .() example to each * v3.6.0 * Update CHANGELOG.md * add explicit nested anonymous mixin test * add explicit nested anonymous mixin test result * derp: align test with expected output * v3.7.0 (#3279) * Update CHANGELOG.md * Rewrite the rewriteUrls feature to use same pattern as strictMath-to-math * Update console warning for --relative-urls
1 parent b0228c9 commit 2d43c0b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+466
-63
lines changed

Gruntfile.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,18 @@ module.exports = function (grunt) {
7070

7171
var sauceJobs = {};
7272

73-
var browserTests = [ 'filemanager-plugin',
73+
74+
var browserTests = [
75+
'filemanager-plugin',
7476
'visitor-plugin',
7577
'global-vars',
7678
'modify-vars',
7779
'production',
7880
'rootpath-relative',
81+
'rootpath-rewrite-urls',
7982
'rootpath',
8083
'relative-urls',
84+
'rewrite-urls',
8185
'browser',
8286
'no-js-errors',
8387
'legacy'
@@ -362,6 +366,14 @@ module.exports = function (grunt) {
362366
outfile: 'tmp/browser/test-runner-relative-urls.html'
363367
}
364368
},
369+
rewriteUrls: {
370+
src: ['test/browser/less/rewrite-urls/*.less'],
371+
options: {
372+
helpers: 'test/browser/runner-rewrite-urls-options.js',
373+
specs: 'test/browser/runner-rewrite-urls-spec.js',
374+
outfile: 'tmp/browser/test-runner-rewrite-urls.html'
375+
}
376+
},
365377
rootpath: {
366378
src: ['test/browser/less/rootpath/*.less'],
367379
options: {
@@ -378,6 +390,14 @@ module.exports = function (grunt) {
378390
outfile: 'tmp/browser/test-runner-rootpath-relative.html'
379391
}
380392
},
393+
rootpathRewriteUrls: {
394+
src: ['test/browser/less/rootpath-rewrite-urls/*.less'],
395+
options: {
396+
helpers: 'test/browser/runner-rootpath-rewrite-urls-options.js',
397+
specs: 'test/browser/runner-rootpath-rewrite-urls-spec.js',
398+
outfile: 'tmp/browser/test-runner-rootpath-rewrite-urls.html'
399+
}
400+
},
381401
production: {
382402
src: ['test/browser/less/production/*.less'],
383403
options: {

bin/lessc

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ var path = require('path'),
44
fs = require('../lib/less-node/fs'),
55
os = require('os'),
66
utils = require('../lib/less/utils'),
7-
MATH = require('../lib/less/math-constants'),
7+
Constants = require('../lib/less/constants'),
88
errno,
99
mkdirp;
1010

@@ -476,16 +476,35 @@ function processPluginQueue() {
476476
options.rootpath = match[2].replace(/\\/g, '/');
477477
}
478478
break;
479-
case 'ru':
480479
case 'relative-urls':
481-
options.relativeUrls = true;
480+
console.warn('The --relative-urls option has been deprecated. Use --rewrite-urls=all.');
481+
options.rewriteUrls = Constants.RewriteUrls.ALL;
482+
break;
483+
case 'ru':
484+
case 'rewrite-urls':
485+
var m = match[2];
486+
if (m) {
487+
if (m === 'local') {
488+
options.rewriteUrls = Constants.RewriteUrls.LOCAL;
489+
} else if (m === 'off') {
490+
options.rewriteUrls = Constants.RewriteUrls.OFF;
491+
} else if (m === 'all') {
492+
options.rewriteUrls = Constants.RewriteUrls.ALL;
493+
} else {
494+
console.error('Unknown rewrite-urls argument ' + m);
495+
continueProcessing = false;
496+
process.exitCode = 1;
497+
}
498+
} else {
499+
options.rewriteUrls = Constants.RewriteUrls.ALL;
500+
}
482501
break;
483502
case 'sm':
484503
case 'strict-math':
485504
console.warn('The --strict-math option has been deprecated. Use --math=strict.');
486505
if (checkArgFunc(arg, match[2])) {
487506
if (checkBooleanArg(match[2])) {
488-
options.math = MATH.STRICT_LEGACY;
507+
options.math = Constants.Math.STRICT_LEGACY;
489508
}
490509
}
491510
break;

lib/less-browser/add-default-options.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,8 @@ module.exports = function(window, options) {
4242
if (options.onReady === undefined) {
4343
options.onReady = true;
4444
}
45+
46+
if (options.relativeUrls) {
47+
options.rewriteUrls = 'all';
48+
}
4549
};

lib/less-browser/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ module.exports = function(window, options) {
9393
currentDirectory: fileManager.getPath(path),
9494
filename: path,
9595
rootFilename: path,
96-
relativeUrls: instanceOptions.relativeUrls};
96+
rewriteUrls: instanceOptions.rewriteUrls
97+
};
9798

9899
newFileInfo.entryPath = newFileInfo.currentDirectory;
99100
newFileInfo.rootpath = instanceOptions.rootpath || newFileInfo.currentDirectory;

lib/less-node/image-size.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module.exports = function(environment) {
66
function imageSize(functionContext, filePathNode) {
77
var filePath = filePathNode.value;
88
var currentFileInfo = functionContext.currentFileInfo;
9-
var currentDirectory = currentFileInfo.relativeUrls ?
9+
var currentDirectory = currentFileInfo.rewriteUrls ?
1010
currentFileInfo.currentDirectory : currentFileInfo.entryPath;
1111

1212
var fragmentStart = filePath.indexOf('#');

lib/less-node/lessc-helper.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ var lessc_helper = {
4747
console.log(' in generated CSS file.');
4848
console.log(' -rp, --rootpath=URL Sets rootpath for url rewriting in relative imports and urls');
4949
console.log(' Works with or without the relative-urls option.');
50-
console.log(' -ru, --relative-urls Re-writes relative urls to the base less file.');
50+
console.log(' -ru=, --rewrite-urls= Rewrites URLs to make them relative to the base less file.');
51+
console.log(' all|local|off \'all\' rewrites all URLs, \'local\' just those starting with a \'.\'');
5152
console.log('');
5253
console.log(' -m=, --math=');
5354
console.log(' always Less will eagerly perform math operations always.');

lib/less/constants.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module.exports = {
2+
Math: {
3+
ALWAYS: 0,
4+
PARENS_DIVISION: 1,
5+
PARENS: 2,
6+
STRICT_LEGACY: 3
7+
},
8+
RewriteUrls: {
9+
OFF: 0,
10+
LOCAL: 1,
11+
ALL: 2
12+
}
13+
};

lib/less/contexts.js

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
var contexts = {};
22
module.exports = contexts;
3-
var MATH = require('./math-constants');
3+
var Constants = require('./constants');
44

55
var copyFromOriginal = function copyFromOriginal(original, destination, propertiesToCopy) {
66
if (!original) { return; }
@@ -18,7 +18,7 @@ var copyFromOriginal = function copyFromOriginal(original, destination, properti
1818
var parseCopyProperties = [
1919
// options
2020
'paths', // option - unmodified - paths to search for imports on
21-
'relativeUrls', // option - whether to adjust URL's to be relative
21+
'rewriteUrls', // option - whether to adjust URL's to be relative
2222
'rootpath', // option - rootpath to append to URL's
2323
'strictImports', // option -
2424
'insecure', // option - whether to allow imports from insecure ssl hosts
@@ -51,7 +51,8 @@ var evalCopyProperties = [
5151
'urlArgs', // whether to add args into url tokens
5252
'javascriptEnabled', // option - whether Inline JavaScript is enabled. if undefined, defaults to false
5353
'pluginManager', // Used as the plugin manager for the session
54-
'importantScope' // used to bubble up !important statements
54+
'importantScope', // used to bubble up !important statements
55+
'rewriteUrls' // option - whether to adjust URL's to be relative
5556
];
5657

5758
contexts.Eval = function(options, frames) {
@@ -95,26 +96,45 @@ contexts.Eval.prototype.isMathOn = function (op) {
9596
if (!this.mathOn) {
9697
return false;
9798
}
98-
if (op === '/' && this.math !== MATH.ALWAYS && (!this.parensStack || !this.parensStack.length)) {
99+
if (op === '/' && this.math !== Constants.Math.ALWAYS && (!this.parensStack || !this.parensStack.length)) {
99100
return false;
100101
}
101-
if (this.math > MATH.PARENS_DIVISION) {
102+
if (this.math > Constants.Math.PARENS_DIVISION) {
102103
return this.parensStack && this.parensStack.length;
103104
}
104105
return true;
105106
};
106107

107-
contexts.Eval.prototype.isPathRelative = function (path) {
108-
return !/^(?:[a-z-]+:|\/|#)/i.test(path);
108+
contexts.Eval.prototype.pathRequiresRewrite = function (path) {
109+
var isRelative = this.rewriteUrls === Constants.RewriteUrls.LOCAL ? isPathLocalRelative : isPathRelative;
110+
111+
return isRelative(path);
109112
};
110113

111-
contexts.Eval.prototype.normalizePath = function( path ) {
114+
contexts.Eval.prototype.rewritePath = function (path, rootpath) {
115+
var newPath;
116+
117+
rootpath = rootpath || '';
118+
newPath = this.normalizePath(rootpath + path);
119+
120+
// If a path was explicit relative and the rootpath was not an absolute path
121+
// we must ensure that the new path is also explicit relative.
122+
if (isPathLocalRelative(path) &&
123+
isPathRelative(rootpath) &&
124+
isPathLocalRelative(newPath) === false) {
125+
newPath = './' + newPath;
126+
}
127+
128+
return newPath;
129+
};
130+
131+
contexts.Eval.prototype.normalizePath = function (path) {
112132
var
113133
segments = path.split('/').reverse(),
114134
segment;
115135

116136
path = [];
117-
while (segments.length !== 0 ) {
137+
while (segments.length !== 0) {
118138
segment = segments.pop();
119139
switch ( segment ) {
120140
case '.':
@@ -127,12 +147,20 @@ contexts.Eval.prototype.normalizePath = function( path ) {
127147
}
128148
break;
129149
default:
130-
path.push( segment );
150+
path.push(segment);
131151
break;
132152
}
133153
}
134154

135155
return path.join('/');
136156
};
137157

158+
function isPathRelative(path) {
159+
return !/^(?:[a-z-]+:|\/|#)/i.test(path);
160+
}
161+
162+
function isPathLocalRelative(path) {
163+
return path.charAt(0) === '.';
164+
}
165+
138166
// todo - do the same for the toCSS ?

lib/less/default-options.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ module.exports = function() {
4242
* that references an image, exactly the same URL will be output in the css.
4343
* This option allows you to re-write URL's in imported files so that the
4444
* URL is always relative to the base imported file */
45-
relativeUrls: false,
45+
rewriteUrls: false,
4646

4747
/* Compatibility with IE8. Used for limiting data-uri length */
4848
ieCompat: false, // true until 3.0

lib/less/functions/data-uri.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module.exports = function(environment) {
1818
var mimetype = mimetypeNode && mimetypeNode.value;
1919
var filePath = filePathNode.value;
2020
var currentFileInfo = this.currentFileInfo;
21-
var currentDirectory = currentFileInfo.relativeUrls ?
21+
var currentDirectory = currentFileInfo.rewriteUrls ?
2222
currentFileInfo.currentDirectory : currentFileInfo.entryPath;
2323

2424
var fragmentStart = filePath.indexOf('#');

lib/less/import-manager.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var contexts = require('./contexts'),
88
module.exports = function(environment) {
99

1010
// FileInfo = {
11-
// 'relativeUrls' - option - whether to adjust URL's to be relative
11+
// 'rewriteUrls' - option - whether to adjust URL's to be relative
1212
// 'filename' - full resolved filename of current file
1313
// 'rootpath' - path to append to normal URLs for this node
1414
// 'currentDirectory' - path to the current file, absolute
@@ -65,7 +65,7 @@ module.exports = function(environment) {
6565
};
6666

6767
var newFileInfo = {
68-
relativeUrls: this.context.relativeUrls,
68+
rewriteUrls: this.context.rewriteUrls,
6969
entryPath: currentFileInfo.entryPath,
7070
rootpath: currentFileInfo.rootpath,
7171
rootFilename: currentFileInfo.rootFilename
@@ -92,7 +92,7 @@ module.exports = function(environment) {
9292
// - If path of imported file is '../mixins.less' and rootpath is 'less/',
9393
// then rootpath should become 'less/../'
9494
newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
95-
if (newFileInfo.relativeUrls) {
95+
if (newFileInfo.rewriteUrls) {
9696
newFileInfo.rootpath = fileManager.join(
9797
(importManager.context.rootpath || ''),
9898
fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));

lib/less/math-constants.js

Lines changed: 0 additions & 6 deletions
This file was deleted.

lib/less/parse.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ module.exports = function(environment, ParseTree, ImportManager) {
4646
var entryPath = filename.replace(/[^\/\\]*$/, '');
4747
rootFileInfo = {
4848
filename: filename,
49-
relativeUrls: context.relativeUrls,
49+
rewriteUrls: context.rewriteUrls,
5050
rootpath: context.rootpath || '',
5151
currentDirectory: entryPath,
5252
entryPath: entryPath,

lib/less/tree/declaration.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ var Node = require('./node'),
22
Value = require('./value'),
33
Keyword = require('./keyword'),
44
Anonymous = require('./anonymous'),
5-
MATH = require('../math-constants');
5+
MATH = require('../constants').Math;
66

77
var Declaration = function (name, value, important, merge, index, currentFileInfo, inline, variable) {
88
this.name = name;

lib/less/tree/expression.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ var Node = require('./node'),
22
Paren = require('./paren'),
33
Comment = require('./comment'),
44
Dimension = require('./dimension'),
5-
MATH = require('../math-constants');
5+
MATH = require('../constants').Math;
66

77
var Expression = function (value, noSpacing) {
88
this.value = value;

lib/less/tree/import.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,18 @@ Import.prototype.evalForImport = function (context) {
9797
};
9898
Import.prototype.evalPath = function (context) {
9999
var path = this.path.eval(context);
100-
var rootpath = this._fileInfo && this._fileInfo.rootpath;
100+
var fileInfo = this._fileInfo;
101101

102102
if (!(path instanceof URL)) {
103-
if (rootpath) {
104-
var pathValue = path.value;
105-
// Add the base path if the import is relative
106-
if (pathValue && context.isPathRelative(pathValue)) {
107-
path.value = rootpath + pathValue;
108-
}
103+
// Add the rootpath if the URL requires a rewrite
104+
var pathValue = path.value;
105+
if (fileInfo &&
106+
pathValue &&
107+
context.pathRequiresRewrite(pathValue)) {
108+
path.value = context.rewritePath(pathValue, fileInfo.rootpath);
109+
} else {
110+
path.value = context.normalizePath(path.value);
109111
}
110-
path.value = context.normalizePath(path.value);
111112
}
112113

113114
return path;

lib/less/tree/operation.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
var Node = require('./node'),
22
Color = require('./color'),
33
Dimension = require('./dimension'),
4-
MATH = require('../math-constants');
4+
MATH = require('../constants').Math;
55

66
var Operation = function (op, operands, isSpaced) {
77
this.op = op.trim();

0 commit comments

Comments
 (0)