Skip to content

Commit

Permalink
Merge pull request #40844 from phillip-kruger/info
Browse files Browse the repository at this point in the history
Show readme in Dev UI
  • Loading branch information
phillip-kruger authored May 27, 2024
2 parents 3076cd3 + bb86f25 commit ff21c43
Show file tree
Hide file tree
Showing 6 changed files with 306 additions and 1 deletion.
43 changes: 43 additions & 0 deletions bom/dev-ui/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,49 @@
<scope>runtime</scope>
</dependency>

<!-- Markdown render -->
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>markdown-it</artifactId>
<version>14.1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>argparse</artifactId>
<version>2.0.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>entities</artifactId>
<version>4.5.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>linkify-it</artifactId>
<version>5.0.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>mdurl</artifactId>
<version>2.0.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>punycode.js</artifactId>
<version>2.3.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>uc.micro</artifactId>
<version>2.1.0</version>
<scope>runtime</scope>
</dependency>
<!-- Qomponent -->
<dependency>
<groupId>org.mvnpm.at.mvnpm</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package io.quarkus.devui.deployment.menu;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;

import io.quarkus.deployment.IsDevelopment;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.devui.deployment.InternalPageBuildItem;
import io.quarkus.devui.runtime.readme.ReadmeJsonRPCService;
import io.quarkus.devui.spi.JsonRPCProvidersBuildItem;
import io.quarkus.devui.spi.page.Page;

/**
* This creates Readme Page
*/
public class ReadmeProcessor {

private static final String NS = "devui-readme";

@BuildStep(onlyIf = IsDevelopment.class)
void createReadmePage(BuildProducer<InternalPageBuildItem> internalPageProducer) {

String readme = getContents("README.md")
.orElse(getContents("readme.md")
.orElse(null));

if (readme != null) {
InternalPageBuildItem readmePage = new InternalPageBuildItem("Readme", 51);

readmePage.addBuildTimeData("readme", readme);

readmePage.addPage(Page.webComponentPageBuilder()
.namespace(NS)
.title("Readme")
.icon("font-awesome-brands:readme")
.componentLink("qwc-readme.js"));

internalPageProducer.produce(readmePage);
}
}

@BuildStep(onlyIf = IsDevelopment.class)
JsonRPCProvidersBuildItem createJsonRPCServiceForCache() {
return new JsonRPCProvidersBuildItem(NS, ReadmeJsonRPCService.class);
}

private Optional<String> getContents(String name) {
Path p = Path.of(name);
if (Files.exists(p)) {
try {
return Optional.of(Files.readString(p));
} catch (IOException ex) {
ex.printStackTrace();
}
}
return Optional.empty();
}
}
38 changes: 38 additions & 0 deletions extensions/vertx-http/dev-ui-resources/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,44 @@
<scope>runtime</scope>
</dependency>


<!-- Markdown it -->
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>markdown-it</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>argparse</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>entities</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>linkify-it</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>mdurl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>punycode.js</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mvnpm</groupId>
<artifactId>uc.micro</artifactId>
<scope>runtime</scope>
</dependency>

<!-- Polyfill for importmaps -->
<dependency>
<groupId>org.mvnpm</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { LitElement, html, css} from 'lit';
import MarkdownIt from 'markdown-it';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { JsonRpc } from 'jsonrpc';
import { readme } from 'devui-data';

/**
* This component shows the Readme page
*/
export class QwcReadme extends LitElement {

jsonRpc = new JsonRpc("devui-readme", true);

static styles = css`
.readme {
padding: 15px;
}
a {
color:var(--quarkus-blue);
}
`;

static properties = {
_readme: {state:true},
};

constructor() {
super();
this.md = new MarkdownIt();
this._readme = readme;
}

connectedCallback() {
super.connectedCallback();
this._observer = this.jsonRpc.streamReadme().onNext(jsonRpcResponse => {
this._readme = jsonRpcResponse.result;
});
}

render() {
if(this._readme){
const htmlContent = this.md.render(this._readme);
return html`<div class="readme">${unsafeHTML(htmlContent)}</div>`;
}
}

}
customElements.define('qwc-readme', QwcReadme);
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class DevUIState extends LitState {
applicationInfo: applicationInfo,
welcomeData: welcomeData,
allConfiguration: allConfiguration,
ideInfo: ideInfo,
ideInfo: ideInfo,
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package io.quarkus.devui.runtime.readme;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.List;
import java.util.Optional;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.enterprise.context.ApplicationScoped;

import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.infrastructure.Infrastructure;
import io.smallrye.mutiny.operators.multi.processors.BroadcastProcessor;
import io.smallrye.mutiny.subscription.Cancellable;

@ApplicationScoped
public class ReadmeJsonRPCService {
private WatchService watchService = null;
private Cancellable cancellable;
private Path path = null;
private final BroadcastProcessor<String> readmeStream = BroadcastProcessor.create();

@PostConstruct
public void init() {
this.path = getPath("README.md")
.orElse(getPath("readme.md")
.orElse(null));
if (this.path != null) {
this.path = this.path.toAbsolutePath();
Path parentDir = this.path.getParent();
try {
watchService = FileSystems.getDefault().newWatchService();
parentDir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);

this.cancellable = Multi.createFrom().emitter(emitter -> {
while (!Thread.currentThread().isInterrupted()) {
WatchKey key;
try {
key = watchService.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
List<WatchEvent<?>> events = key.pollEvents();
for (WatchEvent<?> event : events) {
WatchEvent.Kind<?> kind = event.kind();
Path changed = parentDir.resolve((Path) event.context());

if (changed.equals(this.path)) {
emitter.emit(event);
}
}
boolean valid = key.reset();
if (!valid) {
emitter.complete();
break;
}
}
}).runSubscriptionOn(Infrastructure.getDefaultExecutor())
.onItem().transform(event -> {
readmeStream.onNext(getContent());
return this.path;
}).subscribe().with((t) -> {

});
} catch (IOException e) {
e.printStackTrace();
}
}
}

@PreDestroy
public void cleanup() {
if (cancellable != null) {
cancellable.cancel();
}
try {
if (watchService != null) {
watchService.close();
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

private String getContent() {
try {
return Files.readString(this.path);
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}

public Multi<String> streamReadme() {
return readmeStream;
}

private Optional<Path> getPath(String name) {
Path p = Path.of(name);
if (Files.exists(p)) {
return Optional.of(p);
}
return Optional.empty();
}

}

0 comments on commit ff21c43

Please sign in to comment.