-
Notifications
You must be signed in to change notification settings - Fork 847
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
[feature] include should preserve indention #176
Comments
I suppose that would be nice, but I can't think of a sane way to do it (unless you can). For now, your best option is to use an html beautifier like htmltidy or beautifier. CC: @mde @TimothyGu |
In this specific example it could be run through some post processing, but not say if it were python or yaml which care about whitespace. Since yeoman is using this to help generate code, probably would be nice to support this. I can try and look through the code to see if I see a way to do it. |
Look through it seems like its just a matter of passing the indention of the < for the include to the next function. Then before printing the string, split on '\n' and prepend the indention to every line. |
I'll let @mde & @TimothyGu decide if this is something to implement. |
EJS was designed to be barebones, without the bells and whistles. That gives it its performance, but yes, it does mean that features like indentation have to go. Think of EJS as a C preprocessor if you are familiar with how it works, that gets its job done but gives ugly output. @a86c6f7964, to solve your immediate problem, if you have control over the contents of Aside from that, honestly I don't believe that Yeoman's choice of using EJS is the best one, since Yeoman doesn't care about performance (nor should it), and there are many other template engines out there that are slower, but give better looking output, etc. |
FWIW, the reason was keeping compatibility with underscore templates. Also, I don't agree ejs doesn't care about indentation (also for performance reason is total bollocks come on). Right now you have a ton of whitespace and indentation related features like whitespace trim or the slurp mode. So maybe you don't want to support that feature - and that's totally fine. But don't go on saying ejs as a template language doesn't care about the output as this is false. |
BTW, you could also write your own function, like this:
Then you could do something like |
@SBoudrias said:
Hmm. #55 (comment).
Just wanted to apologize for my tone in my last comment. I just realized that EJS right now was very different from the EJS I worked on a year ago. A year ago, I was optimizing EJS as if it was a finished product, i.e. literally to the last inch, including replace costly I approached this issue as if EJS still cared about compilation performance, but seems like we don't any more. More specifically, features like So again, I apologize. EJS has become something I didn't think it was, and that anachronism in my head led to my comment. On a more technical side, yes, those features might be doable, but will be hard to implement nevertheless. If dynamic inclusion is used, then a run-time solution like the one posed by @RyanZim would be much easier to use. |
@mde thoughts? |
This is not practical, since I was hoping to write something that would be genric and used in multiple places (hence is being included otherwise what is the point) and the indention is different in different places.
The fact that it is seemingly okay to be able to write something like this, should imply to me that it should be supported by the library. Essentially all I am asking is that ejs do that function be default. I am not super excited about having to keep track of the number of spaces I want something indented in the code (seems like a fair work around) but seems super easy to mess up. |
Unless @mde disagrees, we would be open to a PR. It would be best to expose this functionality behind a flag IMO. @mde? CC: @TimothyGu |
This is super important when using jade 😄 |
@canastro Care to contribute? |
I'm sorry at the moment I don't have the time to understand the codebase and fix this issue 😟 |
Hi, I'd really love to have the indents in place, too. Thanks a lot! |
I had the same thought as @a86c6f7964: I wanted indentation. @RyanZim's idea for an Note that my code runs on Node.js or an environment which provides similar APIs. const path = require('path');
const fileSystem = require('fs');
const ejs = require('ejs');
function render(outerTemplatePath, data) {
// Steal the "path base" from the passed template path, create a function which resolves paths based on that base, and
// make the passed template path relative to it (overwriting the argument).
const resolveTemplatePath = (function defineResolveTemplatePath() {
const templatePathsBase = path.dirname(outerTemplatePath);
outerTemplatePath = path.relative(templatePathsBase, outerTemplatePath);
return path.resolve.bind(path, templatePathsBase);
})();
// (Define the options which are passed to readFileSync.)
const utf8EncodingOptions = {
encoding: 'utf8'
};
// Define the regular expression used to find newlines while applying indentation.
const newLineMatcher = /\n/g;
// Define the include function. This function loads the templates and feeds them through ejs.
function include(templatePath, indentation) {
// Load the template.
var template;
try {
template = fileSystem.readFileSync(
resolveTemplatePath(templatePath),
utf8EncodingOptions
);
} catch (error) {
throw new Error([
['Unable to load template: ', templatePath].join(''),
['Note that the path to the template is resolved relative to the path of this template: ', outerTemplatePath].join(''),
error.message
].join('\n'));
}
// Render using ejs.
var result;
try {
result = ejs.render(
template,
data
);
} catch (error) {
throw new Error([
['Unable to render template: ', templatePath].join(''),
error.message
].join('\n'));
}
// Trim the ejs output.
result = result.trim();
// Apply the indentation.
if (undefined !== indentation) {
result = result.replace(
newLineMatcher,
'\n' + indentation
);
}
return result;
}
// Inject the include function into the passed data. This makes the function available for use in the templates. (Note
// that this the if overwrites the argument; while the else alters it. The latter might cause issues if someone passes
// a long-lived object as data.)
if (undefined === data) {
data = {
include
};
} else /* if (undefined !== data) */ {
Object.assign(
data,
{
include
}
);
}
// Include the outer template.
return include(outerTemplatePath, undefined);
} The original example (above) would become this (note the second argument passed to
I am not very familiar with the inner workings of ejs and not at all with its design philosophy, so this might be silly. But it currently works for me, and it might work for the next person to Google Search themselves here. If anyone does end up copying this snippet, note that there's a |
Not sure if there's any value in pointing out issues with a five year old comment, but the above function will not produce desired output for a few reasons: 1) you've lost all your newlines, 2) the spaces are being added to the ends of the lines, and 3) unless there's some magic in the ejs compiler I've overlooked, nothing is actually returned. The following will indent non-empty lines |
If someone does
and other.ejs is
Then it should look like
Instead of
The text was updated successfully, but these errors were encountered: