Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -215,16 +215,19 @@ public List<RoqFrontMatterRawTemplateBuildItem> resolveItems(RoqProjectBuildItem
List<RoqFrontMatterRawTemplateBuildItem> items = new ArrayList<>();
roqProject.consumeRoqDir(
createRoqDirConsumer(quteConfig, config, markupList, headerParserList, watch, dataModifications,
roqProject,
templatePathProducer, generatedResourceProducer, nativeImageResourceProducer, items));

// Scan for layouts & theme-layouts in classpath root
RoqProjectBuildItem.visitRuntimeResources(TEMPLATES_DIR,
t -> {
scanLayouts(quteConfig, config, markupList, headerParserList, watch, dataModifications, items,
roqProject,
t.getPath().getParent(),
t.getPath(),
TemplateType.LAYOUT);
scanLayouts(quteConfig, config, markupList, headerParserList, watch, dataModifications, items,
roqProject,
t.getPath().getParent(),
t.getPath(),
TemplateType.THEME_LAYOUT);
Expand All @@ -235,6 +238,7 @@ public List<RoqFrontMatterRawTemplateBuildItem> resolveItems(RoqProjectBuildItem
l -> {
watchResourceDir(watch, l);
scanContent(quteConfig, config, markupList, headerParserList, watch, dataModifications, items,
roqProject,
l.getPath().getParent(),
l.getPath());
});
Expand All @@ -246,6 +250,7 @@ public List<RoqFrontMatterRawTemplateBuildItem> resolveItems(RoqProjectBuildItem
// and scan for layouts in this directory
roqProject.consumePathFromRoqResourceDir(TEMPLATES_DIR,
l -> scanLayouts(quteConfig, config, markupList, headerParserList, watch, dataModifications, items,
roqProject,
l.getPath().getParent(), l.getPath(),
TemplateType.LAYOUT));
}
Expand All @@ -259,6 +264,7 @@ private static Consumer<Path> createRoqDirConsumer(
List<RoqFrontMatterQuteMarkupBuildItem> markupList,
List<RoqFrontMatterHeaderParserBuildItem> headerParserList, BuildProducer<HotDeploymentWatchedFileBuildItem> watch,
List<RoqFrontMatterDataModificationBuildItem> dataModifications,
RoqProjectBuildItem roqProject,
BuildProducer<TemplatePathBuildItem> templatePathProducer,
BuildProducer<GeneratedResourceBuildItem> generatedResourceProducer,
BuildProducer<NativeImageResourceBuildItem> nativeImageResourceProducer,
Expand All @@ -274,12 +280,12 @@ private static Consumer<Path> createRoqDirConsumer(
scanTemplates(quteConfig, config, watch, templatePathProducer, generatedResourceProducer,
nativeImageResourceProducer, templatesDir);
// No need to ignore the template as it's not a template root
scanLayouts(quteConfig, config, markupList, headerParserList, watch, dataModifications, items, siteDir,
scanLayouts(quteConfig, config, markupList, headerParserList, watch, dataModifications, items, roqProject, siteDir,
templatesDir,
TemplateType.LAYOUT);
final Path contentDir = siteDir.resolve(config.contentDir());
watchDirectory(contentDir, watch);
scanContent(quteConfig, config, markupList, headerParserList, watch, dataModifications, items, siteDir,
scanContent(quteConfig, config, markupList, headerParserList, watch, dataModifications, items, roqProject, siteDir,
contentDir);
};
}
Expand All @@ -288,6 +294,7 @@ private static void scanContent(QuteConfig quteConfig, RoqSiteConfig config,
List<RoqFrontMatterQuteMarkupBuildItem> markupList,
List<RoqFrontMatterHeaderParserBuildItem> headerParserList, BuildProducer<HotDeploymentWatchedFileBuildItem> watch,
List<RoqFrontMatterDataModificationBuildItem> dataModifications, List<RoqFrontMatterRawTemplateBuildItem> items,
RoqProjectBuildItem roqProject,
Path siteDir,
Path contentDir) {
if (!Files.isDirectory(contentDir)) {
Expand Down Expand Up @@ -318,6 +325,7 @@ private static void scanContent(QuteConfig quteConfig, RoqSiteConfig config,
markupList,
headerParserList,
dataModifications,
roqProject,
collection,
type).accept(p);
});
Expand Down Expand Up @@ -363,6 +371,7 @@ private static void scanLayouts(QuteConfig quteConfig,
BuildProducer<HotDeploymentWatchedFileBuildItem> watch,
List<RoqFrontMatterDataModificationBuildItem> dataModifications,
List<RoqFrontMatterRawTemplateBuildItem> items,
RoqProjectBuildItem roqProject,
Path siteDir,
Path templatesRoot,
TemplateType type) {
Expand All @@ -380,6 +389,7 @@ private static void scanLayouts(QuteConfig quteConfig,
markupList,
headerParserList,
dataModifications,
roqProject,
null,
type);
stream
Expand Down Expand Up @@ -473,6 +483,7 @@ private static Consumer<Path> addBuildItem(
List<RoqFrontMatterQuteMarkupBuildItem> markupList,
List<RoqFrontMatterHeaderParserBuildItem> headerParserList,
List<RoqFrontMatterDataModificationBuildItem> dataModifications,
RoqProjectBuildItem roqProject,
ConfiguredCollection collection,
TemplateType type) {
return file -> {
Expand Down Expand Up @@ -547,16 +558,15 @@ private static Consumer<Path> addBuildItem(
if (isIndex) {
attachments = new ArrayList<>();
if (isSiteIndex) {
// Support legacy static dir
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we support static dir anymore ?

scanAttachments(true, true, siteDir, config, quteConfig, watch, attachments, siteDir,
siteDir.resolve(config.staticDir()));
// Public dir
scanAttachments(true, true, siteDir, config, quteConfig, watch, attachments,
scanResourceSiteAttachments(true, true, siteDir, config, quteConfig, watch, attachments,
siteDir.resolve(config.publicDir()),
siteDir.resolve(config.publicDir()));
// Theme resources
scanThemeAttachments(config, roqProject, attachments);
} else {
// Attachments are in the index parent dir
scanAttachments(true, false, siteDir, config, quteConfig, watch, attachments, file.getParent(),
scanResourceSiteAttachments(true, false, siteDir, config, quteConfig, watch, attachments, file.getParent(),
file.getParent());
}

Expand All @@ -576,7 +586,7 @@ private static String getMarkup(boolean isHtml, RoqFrontMatterQuteMarkupBuildIte
return null;
}

private static void scanAttachments(boolean isAttachmentRoot,
private static void scanResourceSiteAttachments(boolean isAttachmentRoot,
boolean isStaticDir,
Path siteDir,
RoqSiteConfig config,
Expand All @@ -595,7 +605,8 @@ private static void scanAttachments(boolean isAttachmentRoot,
try (DirectoryStream<Path> stream = Files.newDirectoryStream(attachmentDir)) {
for (Path entry : stream) {
if (Files.isDirectory(entry)) {
scanAttachments(false, isStaticDir, siteDir, config, quteConfig, watch, attachments, refDir, entry);
scanResourceSiteAttachments(false, isStaticDir, siteDir, config, quteConfig, watch, attachments, refDir,
entry);
} else if (Files.isRegularFile(entry)
&& !isFileExcluded(siteDir, config).test(entry)
&& (isStaticDir || !isTemplate(quteConfig).test(entry))) {
Expand All @@ -609,6 +620,48 @@ private static void scanAttachments(boolean isAttachmentRoot,
}
}

private static void scanThemeAttachments(RoqSiteConfig config, RoqProjectBuildItem roqProject,
List<Attachment> attachments) {
final Set<String> existing = attachments.stream().map(Attachment::name).collect(Collectors.toSet());

if (roqProject.isRoqResourcesInRoot()) {
try {
roqProject.consumePathFromRoqResourceDir(config.publicDir(),
p -> scanThemeResources(config, p, config.publicDir(), existing, attachments));
} catch (IOException e) {
throw new RoqSiteScanningException("Error scanning theme resources in classpath root public dir", e);
}
} else {
RoqProjectBuildItem.visitRuntimeResources(config.publicDir(), p -> {
scanThemeResources(config, p, config.publicDir(), existing, attachments);
});
}
}

private static void scanThemeResources(RoqSiteConfig config, PathVisit p, String rootDir, Set<String> existing,
List<Attachment> attachments) {
if (Files.isDirectory(p.getPath())) {
try (Stream<Path> stream = Files.walk(p.getPath())) {
stream.filter(Files::isRegularFile).forEach(file -> {
String name = resolveAttachmentLink(config, file, p.getPath());
if (existing.add(name)) {
attachments.add(new Attachment(name, file));
}
});
} catch (IOException e) {
throw new RoqSiteScanningException("Error scanning theme resources in " + p.getPath(), e);
}
} else if (Files.isRegularFile(p.getPath())) {
String name = p.getRelativePath();
if (name.startsWith(rootDir + "/")) {
name = name.substring(rootDir.length() + 1);
}
if (existing.add(name)) {
attachments.add(new Attachment(name, p.getPath()));
}
}
}

private static boolean hasIndexFile(Path dir) {
try {
return Files
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.quarkiverse.roq.frontmatter.deployment;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class RoqAvatarTest {

@RegisterExtension
static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addAsResource("avatar/application.properties", "application.properties")
.addAsResource("avatar/site"));

@Test
public void testFallbackAvatarIsRenderedAndPublished() {
RestAssured.when().get("/posts/avatar-fallback-test").then().statusCode(200).log().ifValidationFails()
.body("html.body.img.@src", equalTo("/images/roq-default/default-avatar.svg"))
.body("html.body.img.@alt", equalTo("author-jdoe"))
.body(containsString("Avatar fallback test"));

RestAssured.when().get("/images/roq-default/default-avatar.svg").then().statusCode(200).log().ifValidationFails()
.body(containsString("<svg"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
quarkus.roq.resource-dir=avatar/site
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: Avatar Test Home
---

Avatar home
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: Avatar fallback test
author: jdoe
layout: roq-default/post
---

Avatar fallback test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
jdoe:
name: John Doe
avatar: ""
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
---
{@io.quarkiverse.roq.frontmatter.runtime.model.NormalPage page}
<html>
<body>
<h1>{page.title}</h1>
{#insert /}
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
---
{@io.quarkiverse.roq.frontmatter.runtime.model.DocumentPage page}
{#let author=cdi:authors.get(page.data.author)}
<html>
<body>
{#if author && author.avatar}
<img src="{site.image(author.avatar)}" alt="author-{page.data.author}" />
{#else}
<img src="{site.image('roq-default/default-avatar.svg')}" alt="author-{page.data.author}" />
{/if}
<p>{page.title}</p>
</body>
</html>
{/let}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ <h1 class="page-title">{page.title}</h1>
<div class="page-footer">
<div class="footer-links">
<div class="page-share">
<a href="https://twitter.com/intent/tweet?text={page.title}&url={page.url.encoded}"
title="Share on Twitter" rel="nofollow" target="_blank">Twitter</a>
<a href="https://facebook.com/sharer.php?u={page.url.encoded}" title="Share on Facebook"
rel="nofollow" target="_blank">Facebook</a>
<a href="https://bsky.app/intent/compose?text={page.title}%0ACheck%20it%20out%20{page.url.encoded}" title="Share on Bluesky"
rel="nofollow" target="_blank">Bluesky</a>
<a href="https://twitter.com/intent/tweet?text={page.title}&url={page.url.encoded}" title="Share on Twitter"
rel="nofollow" target="_blank">Twitter</a>
<a href="https://facebook.com/sharer.php?u={page.url.encoded}" title="Share on Facebook" rel="nofollow"
target="_blank">Facebook</a>
<a href="https://bsky.app/intent/compose?text={page.title}%0ACheck%20it%20out%20{page.url.encoded}"
title="Share on Bluesky" rel="nofollow" target="_blank">Bluesky</a>
</div>
<div class="page-tag">
{#for tag in page.data.tags.asStrings}
Expand All @@ -51,13 +51,18 @@ <h1 class="page-title">{page.title}</h1>
{#let author=cdi:authors.get(page.data.author)}
{#if author}
<div class="author">
<img src="{site.image(author.avatar)}" alt="author-{page.data.author}"/>
<div class="author-data">
<a target="_blank" href="{author.profile}"
class="author-name">{author.name}</a>
<span class="author-job-title">{author.job}</span>
</div>
</div>
{#if author.avatar}
<img src="{site.image(author.avatar)}" alt="author-{page.data.author}" />
{#else}
<img src="{site.image('roq-default/default-avatar.svg')}" alt="author-{page.data.author}" />
{/if}

<div class="author-data">
<a target="_blank" href="{author.profile}" class="author-name">{author.name}</a>
<span class="author-job-title">{author.job}</span>
</div>
</div>

{/if}
{/let}
{/if}
Expand All @@ -67,4 +72,4 @@ <h1 class="page-title">{page.title}</h1>
{#insert article-end /}
</article> <!-- End Article Page -->

{#insert after-article /}
{#insert after-article /}