Skip to content
This repository was archived by the owner on Mar 3, 2026. It is now read-only.

Commit 372bb45

Browse files
committed
assets: add a replace processor fix jooby-project#1091
1 parent 0228a10 commit 372bb45

6 files changed

Lines changed: 176 additions & 9 deletions

File tree

doc/available-asset-procesors.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838

3939
* [uglify](https://github.com/jooby-project/jooby/tree/master/jooby-assets-uglify): uglify.js optimizer.
4040

41+
* [replace](https://github.com/jooby-project/jooby/tree/master/jooby-assets-replace): replace strings in files while bundling them.
42+
4143
* [requirejs](https://github.com/jooby-project/jooby/tree/master/jooby-assets-requirejs): r.js optimizer.
4244

4345
* [yui-js](https://github.com/jooby-project/jooby/tree/master/jooby-assets-yui-compressor#yui-js): YUI JS optimizer.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# props
2+
3+
Replace strings in files while bundling them.
4+
5+
{{assets-require.md}}
6+
7+
## usage
8+
9+
```
10+
assets {
11+
fileset {
12+
home: ...
13+
}
14+
15+
pipeline {
16+
dist: [replace]
17+
}
18+
19+
replace {
20+
process.env.NODE_ENV: "\"production\""
21+
"\"development\"": "\"production\""
22+
}
23+
}
24+
```
25+
26+
# see also
27+
28+
{{available-asset-procesors.md}}

modules/jooby-assets/src/main/java/org/jooby/assets/AssetOptions.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -203,18 +203,16 @@
203203
*/
204204
package org.jooby.assets;
205205

206-
import static java.util.Objects.requireNonNull;
207-
208-
import java.util.List;
209-
import java.util.Map;
210-
211-
import org.jooby.Route;
212-
import org.jooby.internal.RoutePattern;
213-
214206
import com.google.common.collect.ImmutableList;
215207
import com.typesafe.config.Config;
216208
import com.typesafe.config.ConfigFactory;
217209
import com.typesafe.config.ConfigValueFactory;
210+
import static java.util.Objects.requireNonNull;
211+
import org.jooby.Route;
212+
import org.jooby.internal.RoutePattern;
213+
214+
import java.util.List;
215+
import java.util.Map;
218216

219217
/**
220218
* Base class for {@link AssetProcessor} and {@link AssetAggregator}.
@@ -224,7 +222,7 @@
224222
*/
225223
public class AssetOptions {
226224

227-
private Config options = ConfigFactory.empty();
225+
protected Config options = ConfigFactory.empty();
228226

229227
public AssetOptions set(final String name, final Object value) {
230228
requireNonNull(name, "Option's name is required.");
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.jooby.assets;
2+
3+
import com.typesafe.config.Config;
4+
import org.jooby.MediaType;
5+
6+
import java.util.LinkedHashMap;
7+
import java.util.Map;
8+
import java.util.regex.Matcher;
9+
import java.util.regex.Pattern;
10+
11+
/**
12+
* <h1>replace</h1>
13+
* <p>
14+
* Replace strings in files while bundling them.
15+
* </p>
16+
*
17+
* <h2>usage</h2>
18+
* <pre>
19+
* assets {
20+
* fileset {
21+
* home: ...
22+
* }
23+
*
24+
* pipeline {
25+
* dist: [replace]
26+
* }
27+
*
28+
* replace {
29+
* process.env.NODE_ENV: "\"production\""
30+
* "\"development\"": "\"production\""
31+
* }
32+
* }
33+
* </pre>
34+
*
35+
* @author edgar
36+
*/
37+
public class Replace extends AssetProcessor {
38+
39+
@Override public boolean matches(MediaType type) {
40+
return true;
41+
}
42+
43+
@Override public String process(String filename, String source, Config conf, ClassLoader loader)
44+
throws Exception {
45+
Map<String, String> options = new LinkedHashMap<>();
46+
StringBuilder keys = new StringBuilder();
47+
this.options.withoutPath("excludes").entrySet().forEach(e -> {
48+
String key = e.getKey()
49+
/** Replace \" generated by .conf format: */
50+
.replace("\\\"", "");
51+
if (Character.isJavaIdentifierStart(key.charAt(0))) {
52+
keys.append("(\\b").append(key).append("\\b)");
53+
} else {
54+
keys.append("(").append(key).append(")");
55+
}
56+
options.put(key, e.getValue().unwrapped().toString());
57+
keys.append("|");
58+
});
59+
if (keys.length() > 0) {
60+
keys.setLength(keys.length() - 1);
61+
Pattern pattern = Pattern.compile(keys.toString());
62+
StringBuffer sb = new StringBuffer();
63+
Matcher matcher = pattern.matcher(source);
64+
while (matcher.find()) {
65+
String key = matcher.group();
66+
String value = options.get(key);
67+
matcher.appendReplacement(sb, value);
68+
}
69+
matcher.appendTail(sb);
70+
return sb.toString();
71+
}
72+
return source;
73+
}
74+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.jooby.assets;
2+
3+
import com.typesafe.config.Config;
4+
import com.typesafe.config.ConfigFactory;
5+
import static org.junit.Assert.assertEquals;
6+
import org.junit.Test;
7+
8+
public class ReplaceTest {
9+
10+
@Test
11+
public void replaceProcessEnvNODE_ENV() throws Exception {
12+
assertEquals("if (\"production\" === \"development\") {\n"
13+
+ " console.log('development only')\n"
14+
+ "}\nconsole.log(headprocess.env.NODE_ENVtail)",
15+
new Replace()
16+
.set(conf("env"))
17+
.process("/index.js", "if (process.env.NODE_ENV === \"development\") {\n"
18+
+ " console.log('development only')\n"
19+
+ "}\nconsole.log(headprocess.env.NODE_ENVtail)",
20+
ConfigFactory.empty()));
21+
}
22+
23+
@Test
24+
public void replaceString() throws Exception {
25+
assertEquals("if (\"production\" !== \"production\") {\n"
26+
+ " console.log('development only')\n"
27+
+ "}\n",
28+
new Replace()
29+
.set(conf("quotes"))
30+
.process("/index.js", "if (\"production\" !== \"development\") {\n"
31+
+ " console.log('development only')\n"
32+
+ "}\n",
33+
ConfigFactory.empty()));
34+
}
35+
36+
@Test
37+
public void replaceMultiString() throws Exception {
38+
assertEquals("if (\"production\" !== \"production\") {\n"
39+
+ " console.log('development only')\n"
40+
+ "}\n",
41+
new Replace()
42+
.set(conf("multi"))
43+
.process("/index.js", "if (\"production\" !== \"development\") {\n"
44+
+ " console.log('development only')\n"
45+
+ "}\n",
46+
ConfigFactory.empty()));
47+
}
48+
49+
private Config conf(String path) {
50+
return ConfigFactory.parseResources("replace.conf").getConfig(path);
51+
}
52+
53+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
env {
2+
process.env.NODE_ENV: "\"production\""
3+
}
4+
5+
quotes {
6+
"\"development\"": "\"production\""
7+
}
8+
9+
multi {
10+
process.env.NODE_ENV: "\"production\""
11+
"\"development\"": "\"production\""
12+
}

0 commit comments

Comments
 (0)