1 module duod.pipeline;
2 import duod.compilation;
3 
4 import core.runtime : Runtime;
5 import std..string : format, toLower;
6 import std.path : buildPath, baseName, extension;
7 import std.algorithm : canFind, endsWith;
8 /// Command line paramater that triggers an asset build.
9 enum buildSwitch = "--duod-build";
10 /// A statically served directory.
11 const string staticDir = "public";
12 /// The URL path that `staticDir` is mapped to.
13 const string webStaticDir = "/";
14 /++ This template, when instantiated represents a front end asset.
15  +  The power of this template is in its differing actions from first
16  +  instantiation compared to all others calls.
17  +
18  +  When first instantiated this template will check for a command line
19  +  parameter that matches `buildSwitch` and if found compile the asset
20  +  that it describes. In order to easily utilize this asset the template
21  +  may be used in a mixin inside of a diet template file which will setup
22  +  the HTML required required to include the compiled asset.
23  +
24  +  Param:
25  +      sourcePath =    The path to an assets source, relative to the
26  +                      compiled binary.
27  +/
28 template Require (const string sourcePath) {
29     /// URL path to this asset from the web.
30     const string webPath = buildPath (webStaticDir, baseName(sourcePath));
31     /// Path to the assets source file.
32     const string staticPath = buildPath (staticDir, baseName(sourcePath));
33     /// This is the mixin code for diet templates.
34     const string Require = sourcePath[$-3..$] == "css" ?
35         "output__.put(\"\\n<link rel=\\\"stylesheet\\\" type=\\\"text/css\\\" href=\\\""~webPath~"\\\">\");"
36         :
37         "output__.put(\"\\n<script type=\\\"text/javascript\\\" src=\\\""~webPath~"\\\"></script>\");";
38     shared static this () {
39         if (Runtime.args.canFind (buildSwitch)) {
40             build (sourcePath, staticPath, staticDir, false);
41         }
42     }
43 } unittest {
44     enum testAsset = "unittests/duod-pipeline.js";
45     assert(Require!testAsset == "output__.put(\"\\n<script type=\\\"text/javascript\\\" src=\\\"/duod-pipeline.js\\\"></script>\");");
46 }
47 /++ This is the same as `Require` however it also minifies the output.
48  +
49  +  Param:
50  +      sourcePath =    The path to an assets source, relative to the
51  +                      compiled binary.
52  +/
53 template RequireMin (const string sourcePath) {
54     /// URL path to this asset from the web.
55     const string webPath = buildPath (webStaticDir, baseName(sourcePath));
56     /// Path to the assets source file.
57     const string staticPath = buildPath (staticDir, baseName(sourcePath));
58     /// This is the mixin code for diet templates.
59     const string RequireMin = sourcePath[$-3..$] == "css" ?
60         "output__.put(\"\\n<link rel=\\\"stylesheet\\\" type=\\\"text/css\\\" href=\\\""~webPath~"\\\">\");"
61         :
62         "output__.put(\"\\n<script type=\\\"text/javascript\\\" src=\\\""~webPath~"\\\"></script>\");";
63     shared static this () {
64         if (Runtime.args.canFind (buildSwitch)) {
65             build (sourcePath, staticPath, staticDir, true);
66         }
67     }
68 } unittest {
69     enum testAsset = "unittests/duod-pipeline.js";
70     assert(Require!testAsset == "output__.put(\"\\n<script type=\\\"text/javascript\\\" src=\\\"/duod-pipeline.js\\\"></script>\");");
71 }