Compare commits

...

5 Commits

Author SHA1 Message Date
Jesse Brault
869bef51dd Change version to 0.1.4.
All checks were successful
Groowt Check and Publish / ci (push) Successful in 5m17s
2025-06-01 14:31:31 -05:00
Jesse Brault
db78a190ff Update dependencies. 2025-06-01 14:28:27 -05:00
Jesse Brault
2d6eed2591 Set to 0.1.4-SNAPSHOT version. 2025-06-01 12:11:10 -05:00
Jesse Brault
df395da792 Update Render component to accept multiple items, closures, and default to rendering it to a component writer. 2025-06-01 11:53:30 -05:00
Jesse Brault
13f85325a1 Fix index-out-of-bounds bug with DefaultComponentContext#getAllAncestors. 2025-05-31 23:29:28 -05:00
7 changed files with 69 additions and 25 deletions

9
README.md Normal file
View File

@ -0,0 +1,9 @@
# Groowt (Groovy Web Tools/Templates)
## Project Version-Bumping
Update the version property in `buildSrc/src/main/groovy/groowt/gradle/groowt-conventions.gradle`.
## Dependency Versions
All dependencies and their version refs should be declared in `gradle/libs.versions.toml`.

View File

@ -4,7 +4,7 @@ plugins {
} }
group = 'groowt' group = 'groowt'
version = '0.1.3' version = '0.1.4'
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -3,30 +3,35 @@
[versions] [versions]
antlr = '4.13.2' antlr = '4.13.2'
groovy = '4.0.25' asm = '9.8'
junit = '5.11.4' groovy = '4.0.27'
jakarta-inject = '2.0.1'
jansi = '2.4.2'
jbarchiva = '0.2.2'
jetbrains-annotations = '26.0.2'
junit = '5.13.0'
kotlin = '1.9.25' kotlin = '1.9.25'
log4j = '2.24.3' log4j = '2.24.3'
mockito = '5.15.2' mockito = '5.18.0'
slf4j = '2.0.16' picocli = '4.7.7'
slf4j = '2.0.17'
[libraries] [libraries]
antlr = { module = 'org.antlr:antlr4', version.ref = 'antlr' } antlr = { module = 'org.antlr:antlr4', version.ref = 'antlr' }
antlr-runtime = { module = 'org.antlr:antlr4-runtime', version.ref = 'antlr' } antlr-runtime = { module = 'org.antlr:antlr4-runtime', version.ref = 'antlr' }
asm = 'org.ow2.asm:asm:9.7.1' asm = { module = 'org.ow2.asm:asm', version.ref = 'asm' }
gradle-tooling = 'org.gradle:gradle-tooling-api:8.12.1'
groovy = { module = 'org.apache.groovy:groovy', version.ref = 'groovy' } groovy = { module = 'org.apache.groovy:groovy', version.ref = 'groovy' }
groovy-console = { module = 'org.apache.groovy:groovy-console', version.ref = 'groovy' } groovy-console = { module = 'org.apache.groovy:groovy-console', version.ref = 'groovy' }
groovy-templates = { module = 'org.apache.groovy:groovy-templates', version.ref = 'groovy' } groovy-templates = { module = 'org.apache.groovy:groovy-templates', version.ref = 'groovy' }
jakarta-inject = 'jakarta.inject:jakarta.inject-api:2.0.1' jakarta-inject = { module = 'jakarta.inject:jakarta.inject-api', version.ref = 'jakarta-inject' }
jansi = 'org.fusesource.jansi:jansi:2.4.1' jansi = { module = 'org.fusesource.jansi:jansi', version.ref = 'jansi' }
jbarchiva = 'com.jessebrault.jbarchiva:jbarchiva:0.2.2' jbarchiva = { module = 'com.jessebrault.jbarchiva:jbarchiva', version.ref = 'jbarchiva' }
jetbrains-anotations = 'org.jetbrains:annotations:26.0.2' jetbrains-anotations = { module = 'org.jetbrains:annotations', version.ref = 'jetbrains-annotations' }
junit-jupiter-api = { module = 'org.junit.jupiter:junit-jupiter-api', version.ref = 'junit' } junit-jupiter-api = { module = 'org.junit.jupiter:junit-jupiter-api', version.ref = 'junit' }
kotlin-stdlib = { module = 'org.jetbrains.kotlin:kotlin-stdlib', version.ref = 'kotlin' } kotlin-stdlib = { module = 'org.jetbrains.kotlin:kotlin-stdlib', version.ref = 'kotlin' }
log4j-core = { module = 'org.apache.logging.log4j:log4j-core', version.ref = 'log4j' } log4j-core = { module = 'org.apache.logging.log4j:log4j-core', version.ref = 'log4j' }
log4j-slf4jBinding = { module = 'org.apache.logging.log4j:log4j-slf4j2-impl', version.ref = 'log4j' } log4j-slf4jBinding = { module = 'org.apache.logging.log4j:log4j-slf4j2-impl', version.ref = 'log4j' }
mockito-core = { module = 'org.mockito:mockito-core', version.ref = 'mockito' } mockito-core = { module = 'org.mockito:mockito-core', version.ref = 'mockito' }
mockito-junit = { module = 'org.mockito:mockito-junit-jupiter', version.ref = 'mockito' } mockito-junit = { module = 'org.mockito:mockito-junit-jupiter', version.ref = 'mockito' }
picocli = 'info.picocli:picocli:4.7.6' picocli = { module = 'info.picocli:picocli', version.ref = 'picocli' }
slf4j-api = { module = 'org.slf4j:slf4j-api', version.ref = 'slf4j' } slf4j-api = { module = 'org.slf4j:slf4j-api', version.ref = 'slf4j' }

View File

@ -97,8 +97,7 @@ public class DefaultComponentContext implements ComponentContext {
@Override @Override
public List<ViewComponent> getAllAncestors() { public List<ViewComponent> getAllAncestors() {
final List<ViewComponent> componentStack = this.getRenderContext().getComponentStack(); return this.renderContext.getComponentStack();
return componentStack.subList(1, componentStack.size());
} }
} }

View File

@ -1,26 +1,34 @@
package groowt.view.component.web.lib package groowt.view.component.web.lib
import groowt.view.View import groowt.view.View
import groowt.view.component.runtime.DefaultComponentWriter
class Render extends DelegatingWebViewComponent { class Render extends DelegatingWebViewComponent {
private final Object item private final Object items
Render(Map attr) { Render(Map attr) {
item = Objects.requireNonNull(attr.item, "<Render> attribute 'item' must not be null.") if (attr.item && attr.items) {
throw new IllegalArgumentException("<Render> cannot have both 'item' and 'items' attributes.")
}
this.items = attr.item ? [attr.item] : attr.items ?: []
} }
@Override @Override
protected View getDelegate() { protected View getDelegate() {
return { Writer w -> return { Writer w ->
if (item.respondsTo('renderTo', [Writer] as Class[])) { items.each {
item.renderTo(w) if (it instanceof Closure) {
} else if (item.respondsTo('render')) { it = it()
w << item.render() }
} else { if (it.respondsTo('renderTo', [Writer] as Class[])) {
throw new IllegalArgumentException( it.renderTo(w)
'<Render> must use an item which responds to either renderTo(Writer) or render().' } else if (it.respondsTo('render')) {
) w << it.render()
} else {
def cw = new DefaultComponentWriter(w, context.renderContext, context)
cw << it
}
} }
} }
} }

View File

@ -1,6 +1,5 @@
package groowt.view.component.web.lib package groowt.view.component.web.lib
import groowt.view.component.web.WebViewComponentContext import groowt.view.component.web.WebViewComponentContext
import groowt.view.component.web.WebViewComponentScope import groowt.view.component.web.WebViewComponentScope
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test

View File

@ -1,5 +1,7 @@
package groowt.view.component.web.lib package groowt.view.component.web.lib
import groowt.view.component.web.BaseWebViewComponent
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
class RenderTests extends AbstractWebViewComponentTests { class RenderTests extends AbstractWebViewComponentTests {
@ -20,6 +22,14 @@ class RenderTests extends AbstractWebViewComponentTests {
} }
static final class Hello extends BaseWebViewComponent {
Hello() {
super('Hello, World!')
}
}
@Test @Test
void renderToExample() { void renderToExample() {
doTest(''' doTest('''
@ -44,4 +54,18 @@ class RenderTests extends AbstractWebViewComponentTests {
) )
} }
@Test
void rendersComponent() {
doTest('<Render item={<RenderTests.Hello />} />', 'Hello, World!', context {
configureRootScope {
addWithNoArgConstructor(Hello)
}
})
}
@Test
void rendersItems() {
doTest('<Render items={[0, 1, 2]} />', '012')
}
} }