Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions closure/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ load("//closure/stylesheets:closure_css_binary.bzl", _closure_css_binary = "clos
load("//closure/stylesheets:closure_css_library.bzl", _closure_css_library = "closure_css_library")
load("//closure/templates:closure_java_template_library.bzl", _closure_java_template_library = "closure_java_template_library")
load("//closure/templates:closure_js_template_library.bzl", _closure_js_template_library = "closure_js_template_library")
load("//closure/templates:closure_templates_plugin.bzl", _closure_templates_plugin = "closure_templates_plugin")
load("//closure/testing:closure_js_test.bzl", _closure_js_test = "closure_js_test")
load("//closure/testing:phantomjs_test.bzl", _phantomjs_test = "phantomjs_test")
load("//closure:filegroup_external.bzl", _filegroup_external = "filegroup_external")
Expand All @@ -44,6 +45,7 @@ closure_css_binary = _closure_css_binary
closure_css_library = _closure_css_library
closure_java_template_library = _closure_java_template_library
closure_js_template_library = _closure_js_template_library
closure_templates_plugin = _closure_templates_plugin
closure_js_test = _closure_js_test
phantomjs_test = _phantomjs_test
filegroup_external = _filegroup_external
Expand Down
26 changes: 21 additions & 5 deletions closure/templates/closure_js_template_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
load("//closure/compiler:closure_js_aspect.bzl", "closure_js_aspect")
load("//closure/compiler:closure_js_library.bzl", "closure_js_library")
load("//closure/private:defs.bzl", "SOY_FILE_TYPE", "unfurl")
load("//closure/templates:closure_templates_plugin.bzl", "SoyPluginInfo")

_SOYTOJSSRCCOMPILER = "@com_google_template_soy//:SoyToJsSrcCompiler"

Expand All @@ -30,8 +31,11 @@ def _impl(ctx):
args += ["--shouldGenerateGoogMsgDefs"]
if ctx.attr.bidi_global_dir:
args += ["--bidiGlobalDir=%s" % ctx.attr.bidi_global_dir]
if ctx.attr.plugin_modules:
args += ["--pluginModules=%s" % ",".join(ctx.attr.plugin_modules)]
if ctx.attr.plugins:
args += ["--pluginModules=%s" % ",".join([
m[SoyPluginInfo].generator.module
for m in ctx.attr.plugins
])]
for arg in ctx.attr.defs:
if not arg.startswith("--") or (" " in arg and "=" not in arg):
fail("Please use --flag=value syntax for defs")
Expand All @@ -47,6 +51,16 @@ def _impl(ctx):
for f in dep.closure_js_library.descriptors.to_list():
args += ["--protoFileDescriptors=%s" % f.path]
inputs.append(f)

plugin_transitive_deps = depset(
transitive = [m[SoyPluginInfo].generator.runtime.transitive_runtime_deps for m in ctx.attr.plugins],
).to_list()
inputs.extend(plugin_transitive_deps)
plugin_classpath = [dep.path for dep in plugin_transitive_deps]
if len(plugin_classpath) > 0:
args.insert(0, "--main_advice_classpath=" +
ctx.configuration.host_path_separator.join(plugin_classpath))

ctx.actions.run(
inputs = inputs,
outputs = ctx.outputs.outputs,
Expand All @@ -69,7 +83,9 @@ _closure_js_template_library = rule(
),
"outputs": attr.output_list(),
"globals": attr.label(allow_single_file = True),
"plugin_modules": attr.label_list(),
"plugins": attr.label_list(
providers = [SoyPluginInfo],
),
"should_generate_soy_msg_defs": attr.bool(),
"bidi_global_dir": attr.int(default = 1, values = [1, -1]),
"soy_msgs_are_external": attr.bool(),
Expand All @@ -85,7 +101,7 @@ def closure_js_template_library(
suppress = [],
testonly = None,
globals = None,
plugin_modules = None,
plugins = None,
should_generate_soy_msg_defs = None,
bidi_global_dir = None,
soy_msgs_are_external = None,
Expand All @@ -101,7 +117,7 @@ def closure_js_template_library(
testonly = testonly,
visibility = ["//visibility:private"],
globals = globals,
plugin_modules = plugin_modules,
plugins = plugins,
should_generate_soy_msg_defs = should_generate_soy_msg_defs,
bidi_global_dir = bidi_global_dir,
soy_msgs_are_external = soy_msgs_are_external,
Expand Down
42 changes: 42 additions & 0 deletions closure/templates/closure_templates_plugin.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2019 The Closure Rules Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

SoyPluginInfo = provider(
doc = "provides the module and java_library implementing this plugin",
)

def _impl(ctx):
return [SoyPluginInfo(
generator = struct(
module = ctx.attr.module,
runtime = java_common.merge([dep[JavaInfo] for dep in ctx.attr.deps]),
),
)]

closure_templates_plugin = rule(
implementation = _impl,
doc = "a closure templates plugin providing user-defined functions",
attrs = {
"module": attr.string(
doc = "fully-qualified class name of extension module",
mandatory = True,
),
"deps": attr.label_list(
doc = "java_library rules providing the specified class name",
providers = [JavaInfo],
mandatory = True,
),
},
provides = [SoyPluginInfo],
)
32 changes: 31 additions & 1 deletion closure/templates/test/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ package(default_testonly = True)

licenses(["notice"]) # Apache 2.0

load("//closure:defs.bzl", "closure_java_template_library", "closure_js_library", "closure_js_proto_library", "closure_js_template_library", "closure_js_test")
load("//closure:defs.bzl", "closure_java_template_library", "closure_js_library", "closure_js_proto_library", "closure_js_template_library", "closure_js_test", "closure_templates_plugin")
load("//closure/private:file_test.bzl", "file_test")

closure_js_proto_library(
Expand Down Expand Up @@ -58,6 +58,36 @@ closure_js_template_library(
],
)

closure_js_template_library(
name = "plugin_soy",
srcs = ["plugin.soy"],
plugins = [":plugin_ExampleModule"],
)

java_library(
name = "ExampleModule",
srcs = ["ExampleModule.java"],
deps = [
"@com_google_guava//jar",
"@com_google_inject_extensions_guice_multibindings//jar",
"@com_google_inject_guice//jar",
"@com_google_template_soy//jar",
],
)

closure_templates_plugin(
name = "plugin_ExampleModule",
module = "test.ExampleModule",
deps = [":ExampleModule"],
)

file_test(
name = "plugin_test_toLower",
size = "small",
file = ":plugin.soy.js",
regexp = ".toLowerCase()",
)

file_test(
name = "localized_using_defs_test",
size = "small",
Expand Down
61 changes: 61 additions & 0 deletions closure/templates/test/ExampleModule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2019 The Closure Rules Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package test;

import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.multibindings.Multibinder;
import com.google.template.soy.data.SoyValue;
import com.google.template.soy.data.restricted.StringData;
import com.google.template.soy.exprtree.Operator;
import com.google.template.soy.jssrc.restricted.JsExpr;
import com.google.template.soy.jssrc.restricted.SoyJsSrcFunction;
import com.google.template.soy.shared.restricted.SoyFunction;
import java.util.List;
import java.util.Set;

/**
* An example module providing a custom soy function and js source implementation.
* See {@link https://github.com/google/closure-templates/blob/master/documentation/dev/plugins.md}
*/
public class ExampleModule extends AbstractModule {
/** {@inheritDoc} */
@Override
protected void configure() {
bindFunctions(Multibinder.newSetBinder(binder(), SoyFunction.class));
}

private void bindFunctions(Multibinder<SoyFunction> fns) {
fns.addBinding().to(ToLowerFunction.class);
}

public static class ToLowerFunction implements SoyJsSrcFunction {
@Override
public String getName() {
return "toLower";
}

@Override
public Set<Integer> getValidArgsSizes() {
return ImmutableSet.of(1);
}

@Override
public JsExpr computeForJsSrc(List<JsExpr> args) {
JsExpr arg = args.get(0);
String exprText = "(" + arg.getText() + ").toLowerCase()";
return new JsExpr(exprText, Operator.NOT_EQUAL.getPrecedence());
}
}
}
25 changes: 25 additions & 0 deletions closure/templates/test/plugin.soy
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2019 The Closure Rules Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

{namespace io.bazel.rules.closure.soy.plugin}


/**
* Greets a person, loudly.
*/
{template .greetLoudly}
{@param name: string}
<p>
{toLower('Hello')} <b>{$name}</b>!
{/template}