views:

124

answers:

3

I'm looking for very simple template script for building JS files. It should do only one thing: include one file to another.

Template (main.js)

/*> script.js */

var style = "/*> style.css */";

script.js

var my_script;

style.css

html, body {margin:0; padding:0}
.my-style {background: #fffacc}

Output

var my_script;

var style = "html, body {margin:0; padding:0}\
.my-style {background: #fffacc}";

I've made cat main.js | sed -e 's!/\*> \(.*\) \*/!cat \1!g'. Output from it:

cat script.js

var style = "cat style.css";

How make cat \1 actually work?

I will use it for building UserJS (Greasemonkey scripts). I've few JS and CSS files in my repository. I would like to keep them separate from each other. But result script must be only one, so I need merge all JS and CSS files to it.

I can use sed, awk, perl or ruby.


Finally, I've made js-preprocessor. Thanks guys!

+1  A: 

What’s the intended use for this? JavaScript does not support multi-line strings, so your style variable definition will result in a syntax error after that template expansion.

Edit: my mistake – I missed that your example expansion included a \ continuation. This complicates the expansion process though; it would be good if you could go into some more detail about where you plan to use this, what tools you have available etc.

An example in Ruby:

ruby <main.js -pe'$_.gsub!(%r{/\*>\s*(.+?)\s*\*/}) { File.read($1) }'
Ciarán Walsh
Would be good to see a solution even without a \ handling.
NV
I've made script based on yours. http://gist.github.com/265546. Dirty, but it works!
NV
+4  A: 

There are three obvious solutions:

  1. Don't use any kind of include directive, merely specify the order of files. This lets you use a simple cat file1 file2 file3 > output statement to get the final result.
  2. Use an existing preprocessor, such as the C preprocessor (cpp), but be careful of how it might interact with the JS. You can also use this to your advantage, however, by defining macros in "headers", as is already done for C, creating your own libraries.
  3. Write a simple preprocessor that can do exactly what you want. If you just want to support #include-like directives, this would not be hard.

Non-obvious solutions might use some specific JavaScript engine which allowed you to add hooks or plugins to support file inclusion, outputting the resulting code, or maybe something else entirely.

Roger Pate
1. This works only on simple cases 2. Good idea, but it doesn't work. How could I replace `var style = "/*> style.css */"` with #include directive? `var style='#include "style.css"'` doesn't work, because #include just a string.
NV
Yes, #1 requires making sure your files are in the correct format and trades flexibility for simplicity. #2 requires you to follow the specific preprocessor's conventions, but there's more options than cpp, such as m4 and others. #3 is the only one where you get complete control and can apply any transformation you want, without restriction---it is also the most complex.
Roger Pate
To apply #2 to your example files, using cpp, I'd either make style.css a valid C string literal (C allows backslashes before newlines in a string literal just like JS, so that particular problem is taken care of) and #include it, or make that file define a macro to use `var style = MYSTYLE;`. (Either way, I'd rename it to style.css.inc or similar.)
Roger Pate
Also remember you could even generate style.css.inc from style.css with a simple program that transformed it into a valid C string literal. A simple makefile will handle the dependencies and generation of all this for you, too.
Roger Pate
A: 

I would use also ruby but I suggest to rely on erb which is included in ruby stdlib. It allows extensibility if you want to add more complex features.

In your case you could write the following method:

def include_file(filename)
  File.open( filename, "r" ) { |f| f.read }
end

And then use it from you template:

<% include_file "script.js"  %>
var style = "<% include_file "style.css"  %>";

It just works...

paradigmatic