This repository has been archived by the owner on Jan 9, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 67
@import doesn't work when compiler ran on string #28
Comments
So I poked around at the problem a bit more, and after getting frustrated trying to get envjs working 100% in this scenario, I decided to just process the imports directly in the java code instead of trying to handle the imports with xhr() in the javascript code :) class LessCompilerMod extends LessCompiler {
Pattern importPattern = Pattern.compile("['\"]([^'\"]+)['\"]");
boolean onlyImportOnce = true; // does @import always act like @import-once (like in Less 1.4+)
public String compile(String input, URI baseUri) throws LessException {
StringBuilder merged = new StringBuilder();
BufferedReader reader = new BufferedReader(new StringReader(input));
String line;
try {
List<String> imported = new ArrayList<>();
while ((line = reader.readLine()) != null) {
merged.append(readLineAndProcessImports(line, baseUri, 0, imported));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return super.compile(merged.toString());
}
StringBuilder readLineAndProcessImports(String line, URI baseUri, int level, List<String> imported) throws LessException {
if (level >= 10) {
throw new LessException("Max @import levels exceeded(" + level + "), possible recursion!",
new AssertionError("recursion depth exceeded"));
}
StringBuilder merged = new StringBuilder();
LOGGER.trace(line);
if (line.contains("@import")) {
LOGGER.debug("Found an import: {}", line);
Matcher match = importPattern.matcher(line);
if (match.find()) {
String path = match.group(1);
if (!path.endsWith(".less") && !path.endsWith(".css")) {
path += ".less";
}
URI fullPath;
fullPath = baseUri.resolve(path);
LOGGER.debug("@import fullPath is '{}'", fullPath);
if ((onlyImportOnce || line.contains("@import-once")) && imported.contains(fullPath.toString())) {
LOGGER.info("Already included: {}", line);
} else {
if (!imported.contains(fullPath.toString())) {
imported.add(fullPath.toString());
}
try (InputStream stream = fullPath.toURL().openStream()) {
InputStreamReader importReader = new InputStreamReader(stream);
BufferedReader importBuffered = new BufferedReader(importReader);
String importedLine;
while ((importedLine = importBuffered.readLine()) != null) {
LOGGER.trace(importedLine);
if (importedLine.contains("@import")) {
LOGGER.debug("Found a sub import: {}", importedLine);
merged.append(readLineAndProcessImports(importedLine, baseUri, level + 1, imported));
} else {
merged.append(importedLine);
}
}
} catch (IOException e) {
throw new LessException(e);
}
}
} else {
LOGGER.warn("Unable to find a resource path in line: {}", line);
}
} else {
merged.append(line);
}
return merged;
}
} I call it like this: LessCompilerMod compiler = new LessCompilerMod();
compiler.setEncoding(charset);
compiler.setCompress(false);
String css = compiler.compile(new String(wrapper.getBytes(), this.charset), new URI("file:///home/user/Projects/myproject/src/main/webapp/css/")); |
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
I created a simple LessCss filter for webutilities: http://code.google.com/p/webutilities/issues/detail?id=46 but unfortunately, when using LessCompiler.compile(String data) @imports don't work.
When a relative path is specified, I see this error:
org.lesscss.LessException: Couldn't load undefinedvariables.less (0)
That's understandable, obviously the import doesn't know where the path is relative from
However changing '@ import' to the full path still doesn't work:
org.lesscss.LessException: Couldn't load file:///full/path/to/file/css/variables.less (undefined)
I think it comes from envjs returning a different status for file:/// paths than browsers, the xhs.status is undefined even though the file was loaded properly (was able to hack less.js to make it ignore the return status and it worked).
If this bug can be fixed, a great enhancement would be a new function in LessCompiler:
LessCompiler.compile(String data, URL basePath); so imports would more easily work when processing data in a servlet context like the filter does.
The text was updated successfully, but these errors were encountered: