
io.helidon.build.maven.sitegen.VuetifyBackend Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2018, 2025 Oracle and/or its affiliates.
*
* 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 io.helidon.build.maven.sitegen;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.stream.Stream;
import io.helidon.build.common.SourcePath;
import io.helidon.build.maven.sitegen.freemarker.FreemarkerEngine;
import io.helidon.build.maven.sitegen.freemarker.TemplateSession;
import io.helidon.build.maven.sitegen.models.Nav;
import io.helidon.build.maven.sitegen.models.Page;
import static io.helidon.build.common.FileUtils.resourceAsPath;
import static io.helidon.build.common.Strings.requireValid;
import static io.helidon.build.maven.sitegen.Context.copyResources;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
/**
* A backend implementation for Vuetify.
*
* @see https://vuetifyjs.com
*/
public class VuetifyBackend extends Backend {
/**
* The Vuetify backend name.
*/
public static final String BACKEND_NAME = "vuetify";
private final Nav nav;
private final Map theme;
private final Path staticFiles;
private final String home;
private final List releases;
private VuetifyBackend(Builder builder) {
super(BACKEND_NAME);
theme = builder.theme;
nav = builder.nav;
home = requireValid(builder.home, "home is invalid!");
releases = builder.releases;
staticFiles = resourceAsPath("/files/vuetify", VuetifyBackend.class);
}
/**
* Get the navigation tree root.
*
* @return navigation tree root or {@code null} if not set
*/
public Nav nav() {
return nav;
}
/**
* Get the theme.
*
* @return map, never {@code null}
*/
public Map theme() {
return theme;
}
/**
* Get the home.
*
* @return home or {@code null} if not set
*/
public String home() {
return home;
}
/**
* Get the releases.
*
* @return list, never {@code null}
*/
public List releases() {
return releases;
}
@Override
public void generate(Context ctx) {
Map pages = ctx.pages();
Page home = pages.get(new SourcePath(this.home).asString(false));
if (home == null) {
throw new IllegalStateException("unable to get home page");
}
// resolve navigation
Nav resolvedNav;
List navRoutes;
if (nav != null) {
resolvedNav = resolveNav(ctx);
navRoutes = resolvedNav.items()
.stream()
.flatMap(n -> n.items().isEmpty() ? Stream.of(n) : n.items().stream()) // depth:1
.flatMap(n -> n.items().isEmpty() ? Stream.of(n) : n.items().stream()) // depth:2
.flatMap(n -> n.items().isEmpty() ? Stream.of(n) : n.items().stream()) // depth:3
.map(Nav::to)
.filter(Objects::nonNull)
.collect(toList());
} else {
resolvedNav = null;
navRoutes = List.of();
}
Path pagesDir = ctx.outputDir().resolve("pages");
try {
Files.createDirectories(pagesDir);
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
// render all pages
ctx.processPages(pagesDir, "js");
// copy declared assets
ctx.copyStaticAssets();
TemplateSession session = ctx.templateSession();
Map pagesByRoute = pages.values()
.stream()
.map(p -> Map.entry(p.target(), p))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
// resolve all routes
List routes = new ArrayList<>();
routes.add(home.target());
navRoutes.forEach(r -> {
if (!routes.contains(r)) {
routes.add(r);
}
});
pagesByRoute.keySet().forEach(r -> {
if (!routes.contains(r)) {
routes.add(r);
}
});
Map allBindings = session.vueBindings().bindings();
Map model = new HashMap<>();
model.put("searchEntries", session.searchIndex().entries());
model.put("navRoutes", navRoutes);
model.put("allRoutes", routes);
model.put("customLayoutEntries", session.customLayouts().mappings());
model.put("pages", pagesByRoute);
model.put("metadata", home.metadata());
model.put("nav", resolvedNav);
model.put("header", ctx.site().header());
model.put("theme", theme);
model.put("home", home);
model.put("releases", releases);
model.put("bindings", allBindings);
FreemarkerEngine freemarker = ctx.site().engine().freemarker();
Path outputDir = ctx.outputDir();
// custom bindings
for (Page page : pages.values()) {
String bindings = allBindings.get(page.source());
if (bindings != null) {
Map bindingsModel = new HashMap<>(model);
bindingsModel.put("bindings", bindings);
bindingsModel.put("page", page);
String path = "pages/" + page.target() + "_custom.js";
freemarker.renderFile("custom_bindings", path, bindingsModel, outputDir);
}
}
// render search-index.js
freemarker.renderFile("search_index", "main/search-index.json", model, outputDir);
// render index.html
freemarker.renderFile("index", "index.html", model, outputDir);
// render main/config.js
freemarker.renderFile("config", "main/config.js", model, outputDir);
// copy vuetify resources
copyResources(staticFiles, ctx.outputDir());
}
private Nav resolveNav(Context ctx) {
Map pages = ctx.pages();
Deque builders = new ArrayDeque<>();
Deque
© 2015 - 2025 Weber Informatics LLC | Privacy Policy