html exporter fixed
This commit is contained in:
@@ -12,6 +12,8 @@ public class ExportOptions {
|
||||
boolean renderChoicesAsDiamonds = true;
|
||||
@Builder.Default
|
||||
boolean embedIdentifiers = false;
|
||||
@Builder.Default
|
||||
boolean includeMetadataPane = true;
|
||||
|
||||
@Builder.Default
|
||||
EnumFormat eventFormat = EnumFormat.fn;
|
||||
|
||||
@@ -56,6 +56,9 @@ public class HtmlExporterCommand implements Callable<Integer> {
|
||||
@Option(names = {"--no-diamonds"}, description = "Disable rendering choice pseudostates as PlantUML diamonds (render them as normal state nodes instead).")
|
||||
private boolean noDiamonds;
|
||||
|
||||
@Option(names = {"--no-metadata-pane"}, description = "Disable rendering the left metadata pane (entry points, flows) in the HTML viewer.")
|
||||
private boolean noMetadataPane;
|
||||
|
||||
@Override
|
||||
public Integer call() throws Exception {
|
||||
var out = spec.commandLine().getOut();
|
||||
@@ -78,12 +81,17 @@ public class HtmlExporterCommand implements Callable<Integer> {
|
||||
List<String> formats = List.of("html", "json");
|
||||
List<String> profiles = activeProfiles != null ? activeProfiles : java.util.Collections.emptyList();
|
||||
|
||||
if (noMetadataPane) {
|
||||
System.setProperty("html.hideMetadataPane", "true");
|
||||
}
|
||||
|
||||
if (jsonFile != null) {
|
||||
exportService.runJsonExporter(jsonFile, outputDir, formats, profiles);
|
||||
} else {
|
||||
boolean renderChoicesAsDiamonds = !noDiamonds;
|
||||
exportService.runExporter(inputDir, outputDir, formats, renderChoicesAsDiamonds, profiles, flowsFile, machineFilter);
|
||||
}
|
||||
System.clearProperty("html.hideMetadataPane");
|
||||
|
||||
out.println(CommandLine.Help.Ansi.AUTO.string("%n@|bold,green SUCCESS:|@ Interactive documentation generated successfully."));
|
||||
|
||||
|
||||
@@ -56,12 +56,51 @@ public class HtmlExporter implements StateMachineExporter {
|
||||
// 5. Prepare Metadata JSON
|
||||
String metadataJson = objectMapper.writeValueAsString(result);
|
||||
|
||||
// Check if we should render metadata pane
|
||||
boolean hideMetadataProp = Boolean.getBoolean("html.hideMetadataPane");
|
||||
boolean hasEntryPoints = result.getMetadata() != null && result.getMetadata().getEntryPoints() != null && !result.getMetadata().getEntryPoints().isEmpty();
|
||||
boolean hasFlows = result.getFlows() != null && !result.getFlows().isEmpty();
|
||||
boolean shouldRenderPane = !hideMetadataProp && options.isIncludeMetadataPane() && (hasEntryPoints || hasFlows);
|
||||
|
||||
// 6. Inject Data
|
||||
return template
|
||||
String finalHtml = template
|
||||
.replace("{{MACHINE_NAME}}", result.getName())
|
||||
.replace("{{SVG_CONTENT}}", decoratedSvg)
|
||||
.replace("{{METADATA_JSON}}", metadataJson);
|
||||
|
||||
if (shouldRenderPane) {
|
||||
// If template.html uses {{SIDEBAR_HTML}} and {{TOGGLE_BUTTON_HTML}}, replace with actual HTML
|
||||
finalHtml = finalHtml.replace("{{SIDEBAR_HTML}}", "<div id=\"sidebar\">\n" +
|
||||
" <div class=\"sidebar-header\">\n" +
|
||||
" <header>\n" +
|
||||
" <h1>Explorer</h1>\n" +
|
||||
" <p>{{MACHINE_NAME}}</p>\n" +
|
||||
" </header>\n" +
|
||||
" </div>\n" +
|
||||
" \n" +
|
||||
" <div class=\"tabs\">\n" +
|
||||
" <div class=\"tab active\" data-tab=\"explorer\">Explorer</div>\n" +
|
||||
" <div class=\"tab\" data-tab=\"flows\">Business Flows</div>\n" +
|
||||
" </div>\n" +
|
||||
"\n" +
|
||||
" <div id=\"tab-explorer\" class=\"tab-content active\">\n" +
|
||||
" <div id=\"ep-list\"></div>\n" +
|
||||
" </div>\n" +
|
||||
"\n" +
|
||||
" <div id=\"tab-flows\" class=\"tab-content\">\n" +
|
||||
" <div id=\"flow-list\"></div>\n" +
|
||||
" </div>\n" +
|
||||
"</div>").replace("{{MACHINE_NAME}}", result.getName());
|
||||
|
||||
finalHtml = finalHtml.replace("{{TOGGLE_BUTTON_HTML}}", " <button id=\"toggle-sidebar\" aria-label=\"Toggle Sidebar\" title=\"Toggle Sidebar\">\n" +
|
||||
" <svg viewBox=\"0 0 24 24\"><path d=\"M4 6h16M4 12h16M4 18h16\"></path></svg>\n" +
|
||||
" </button>");
|
||||
} else {
|
||||
finalHtml = finalHtml.replace("{{SIDEBAR_HTML}}", "").replace("{{TOGGLE_BUTTON_HTML}}", "");
|
||||
}
|
||||
|
||||
return finalHtml;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to export to HTML", e);
|
||||
throw new RuntimeException("HTML export failed", e);
|
||||
|
||||
@@ -261,32 +261,10 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<header>
|
||||
<h1>Explorer</h1>
|
||||
<p>{{MACHINE_NAME}}</p>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div class="tabs">
|
||||
<div class="tab active" data-tab="explorer">Explorer</div>
|
||||
<div class="tab" data-tab="flows">Business Flows</div>
|
||||
</div>
|
||||
|
||||
<div id="tab-explorer" class="tab-content active">
|
||||
<div id="ep-list"></div>
|
||||
</div>
|
||||
|
||||
<div id="tab-flows" class="tab-content">
|
||||
<div id="flow-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
{{SIDEBAR_HTML}}
|
||||
|
||||
<div id="main">
|
||||
<button id="toggle-sidebar" aria-label="Toggle Sidebar" title="Toggle Sidebar">
|
||||
<svg viewBox="0 0 24 24"><path d="M4 6h16M4 12h16M4 18h16"></path></svg>
|
||||
</button>
|
||||
{{TOGGLE_BUTTON_HTML}}
|
||||
<div id="svg-container">
|
||||
{{SVG_CONTENT}}
|
||||
</div>
|
||||
@@ -304,9 +282,11 @@
|
||||
const svg = document.querySelector('#svg-container svg');
|
||||
panZoomInstance = svgPanZoom(svg, { zoomEnabled: true, controlIconsEnabled: true, fit: true, center: true });
|
||||
|
||||
document.getElementById('toggle-sidebar').addEventListener('click', () => {
|
||||
const toggleSidebar = document.getElementById('toggle-sidebar');
|
||||
if (toggleSidebar) {
|
||||
toggleSidebar.addEventListener('click', () => {
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
sidebar.classList.toggle('collapsed');
|
||||
if (sidebar) sidebar.classList.toggle('collapsed');
|
||||
|
||||
// Re-center SVG pan-zoom after transition
|
||||
setTimeout(() => {
|
||||
@@ -316,6 +296,7 @@
|
||||
}
|
||||
}, 300);
|
||||
});
|
||||
}
|
||||
|
||||
setupTabs();
|
||||
populateSidebar();
|
||||
@@ -325,8 +306,10 @@
|
||||
|
||||
function setupTabs() {
|
||||
const flows = metadata.flows || [];
|
||||
const tabsEl = document.querySelector('.tabs');
|
||||
if (!tabsEl) return;
|
||||
if (flows.length === 0) {
|
||||
document.querySelector('.tabs').style.display = 'none';
|
||||
tabsEl.style.display = 'none';
|
||||
document.querySelector('.tab-content[data-tab="flows"]')?.remove();
|
||||
return;
|
||||
}
|
||||
@@ -342,6 +325,7 @@
|
||||
|
||||
function populateSidebar() {
|
||||
const list = document.getElementById('ep-list');
|
||||
if (!list) return;
|
||||
const entryPoints = metadata.metadata.entryPoints || [];
|
||||
const machineEvents = new Set(metadata.transitions.map(t => t.event).filter(Boolean));
|
||||
|
||||
@@ -372,6 +356,7 @@
|
||||
|
||||
function populateFlows() {
|
||||
const list = document.getElementById('flow-list');
|
||||
if (!list) return;
|
||||
const flows = metadata.flows || [];
|
||||
|
||||
if (flows.length === 0) {
|
||||
|
||||
Reference in New Issue
Block a user