1 /++ This module implements the compilation functionality.
2  +  Provides commands to compile and minify assets from their source with duod.
3  +/
4 module duod.compilation;
5 import duod.utilities;
6 import std.exception : enforce;
7 import std..string : format, chompPrefix, toLower;
8 import std.file : readText, write, getSize, mkdirRecurse, dirName;
9 import std.path : buildPath, extension;
10 import std.stdio : writeln;
11 /++ Build a css or js asset based on the given string. This exposes the core
12  +  functionality of the duo frontend package manager and as such, may pull in
13  +  additional assets such as fonts or images, which should be placed in a
14  +  directory for static file serving, the default, as with vibe.d is `public/`.
15  +  Params:
16  +      source    =     Source code to pass to duo.
17  +      js        =     If this is javascript or css. Default true for javascript.
18  +      staticdir =     Your statically served asset directory. Default is `public/`
19  +  Returns: The duo outputed source file with all external assets built in.
20  +/
21 string duo (string source, bool js=true, string staticdir="public") {
22     enforce (hasDuo, "Duo command not available, please install");
23 
24     string command = format ("duo -o %s -t %s -c -S -q",
25             staticdir, js ? "js" : "css");
26     return getOutput (command, source);
27 }
28 /++ Compress assets via uglifying (aka minifying) them with yuglify.
29  +  This takes in javascript or css and can output code with the
30  +  same functionality at a fraction of the size.
31  +  Params:
32  +      source =     Source code to pass to yuglify.
33  +      js     =     If this is javascript or css. Default true for javascript.
34  +  Returns: The inputted source code without formatting which results in a size decrease.
35  +/
36 string uglify (string source, bool js=true) {
37     enforce (hasYuglify, "Uglify command not available");
38 
39     string command = format ("yuglify --terminal --type %s",
40             js ? "js" : "css");
41     return getOutput (command, source);
42 }
43 /++ Compile the given asset source with duo and optionally minify/uglify the output.
44  +  Params:
45  +      source    =     Source code to pass to compile.
46  +      js        =     If this is javascript or css. Default true for javascript.
47  +      staticdir =     Your statically served asset directory. Default is `public/`
48  +      min       =     If true the output will be minified/uglifies with yuglify.
49  +  Returns: The duo builtsource code without formatting which results in a size decrease.
50  +/
51 string compile (string source, bool js=true, string staticdir="public", bool min=true) {
52     string compiled = duo (source, js, staticdir);
53     return min ? uglify (compiled, js) : compiled;
54 }
55 /++ Much the same as `compile` however `build` takes and outputs files.
56  +  Params:
57  +      sourcePath =    Path to asset source to be built.
58  +      staticPath =    Path to the compile assets output destination.
59  +      staticdir  =    Your statically served asset directory. Default is `public/`
60  +      min       =     If true the output will be minified/uglifies with yuglify.
61  +/
62 void build (string sourcePath, string staticPath, string staticdir="public", bool min=true) {
63     string source = compile(
64             readText (sourcePath),
65             extension(staticPath).toLower() == ".js", staticdir, hasYuglify && min);
66     staticPath.dirName.mkdirRecurse;
67 
68     write (staticPath, source);
69     writeln (format ("Compiled asset %s to %s which is %s bytes.",
70                 sourcePath, staticPath, getSize(staticPath)));
71 }