diff --git a/docs/Beck.Docs/Content/docs/guides/pennington.md b/docs/Beck.Docs/Content/docs/guides/pennington.md index 5d7fb6d..e8bd9e2 100644 --- a/docs/Beck.Docs/Content/docs/guides/pennington.md +++ b/docs/Beck.Docs/Content/docs/guides/pennington.md @@ -1,6 +1,6 @@ --- title: Add Beck to a Pennington site -description: Render fenced beck diagrams to static SVG at build time with a code-block preprocessor, measure with your own fonts, and adopt your MonorailCSS palette. +description: Register the Pennington.Beck package so fenced beck diagrams render to static SVG at build time, pick styles per fence or site-wide, measure with your own fonts, and adopt your MonorailCSS palette. order: 21 sectionLabel: Setup uid: docs.guide.pennington @@ -8,88 +8,112 @@ uid: docs.guide.pennington This guide shows you how to add Beck to a [Pennington](https://usepennington.github.io/pennington/) site so a fenced ` ```beck ` block renders to a static, self-animating `` at **build time** — no -client JavaScript. For a generic (non-Pennington) ASP.NET host, see [Add Beck to your -site](/docs/guides/install) instead. +client JavaScript. Pennington ships a first-class integration package, **`Pennington.Beck`**, so the +whole wiring is one package reference and one service registration. For a generic (non-Pennington) +ASP.NET host, see [Add Beck to your site](/docs/guides/install) instead. ## Add the package -Beck renders with **`Beck`**, a pure-C# package. Add **`Beck.Skia`** too — the -preprocessor below measures text with it so cards match your fonts exactly (strongly recommended): - ```bash -dotnet add package Beck -dotnet add package Beck.Skia +dotnet add package Pennington.Beck ``` -## Render fenced diagrams - -Pennington hands every fenced code block to any `ICodeBlockPreprocessor` you register. Add one that -renders the `beck` language through `BeckSvg.Render` and returns finished HTML: +Then register it in `Program.cs`: ```csharp -using Beck.Rendering; -using Beck.Skia; -using Beck.Rendering.Text; -using Pennington.Markdown.Extensions; - -// Turns a ```beck (inline YAML) or ```beck:symbol (a .beck.yaml file path) fence into a static SVG. -// Priority 500 runs it before the source-embed preprocessor, so a `beck` fence is never treated as -// a plain source listing. Add `,static` to a fence for a still frame. -public sealed class BeckFencePreprocessor : ICodeBlockPreprocessor -{ - public int Priority => 500; +builder.Services.AddPenningtonBeck(); +``` - private readonly BeckFontSpec _font = new() - { - Family = "IBM Plex Sans", - MonoFamily = "IBM Plex Mono", - Files = new Dictionary - { - [400] = "wwwroot/fonts/IBMPlexSans-Regular.ttf", - [600] = "wwwroot/fonts/IBMPlexSans-SemiBold.ttf", - [700] = "wwwroot/fonts/IBMPlexSans-Bold.ttf", - }, - MonoFiles = new Dictionary { [400] = "wwwroot/fonts/IBMPlexMono-Regular.ttf" }, - }; +That is the whole integration. `Pennington.Beck` hooks the shared code-block pipeline (it works the +same on `AddPennington`, `AddDocSite`, and `AddBlogSite` hosts), so the next ` ```beck ` fence in any +Markdown page renders as an inline SVG — on the live dev server and in the static build. It brings +the `Beck` engine with it; a malformed diagram fails loud with a visible error box and a diagnostics +entry rather than silently vanishing. - private readonly SkiaTextMeasurer _measurer; - public BeckFencePreprocessor() => _measurer = new SkiaTextMeasurer(_font); +## Tune a fence with flags - public CodeBlockPreprocessResult? TryProcess(string code, string languageId) - { - var id = languageId.Trim(); - if (id != "beck" && !id.StartsWith("beck:") && !id.StartsWith("beck,")) return null; - - bool isFile = id.Contains(":symbol"); - var animation = id.Contains(",static") ? AnimationMode.Static : AnimationMode.Full; - string yaml = isFile ? File.ReadAllText(Path.GetFullPath(code.Trim())) : code; - - string svg = BeckSvg.Render(yaml, new SvgRenderOptions - { - Measurer = _measurer, // exact card sizing over your fonts (see below) - Font = _font, - Animation = animation, - }); - // SkipTransform: this is finished HTML — the highlighter must not reprocess it. - return new CodeBlockPreprocessResult($"
{svg}
", "beck", SkipTransform: true); - } -} +A comma-separated tail after the language adjusts one fence without touching its YAML, and flags +combine (`beck:symbol,static` works): + +| flag | effect | +|---|---| +| `static` | Renders the fully-revealed final frame with no motion. | +| `scrub` | Drives the choreography from scroll position instead of a looping timeline. | +| `style=` | Overrides the document's `meta.style` — render one YAML in any built-in look. | + +## Pick a style + +Beck ships [nine built-in styles](/docs/guides/styles) — `classic`, `minimal`, `terminal`, +`blueprint`, `glow`, `brutalist`, `sketch`, `extrude`, and `circuit`. There are three places to set +one, from narrowest to widest scope: + +**Per document**, in the YAML itself: + +```yaml +type: architecture +meta: + style: sketch +``` + +**Per fence**, with the `style=` flag — a last-word override that beats the document's own +`meta.style`, handy when one shared `.beck.yaml` should appear in different looks: + +````markdown +```beck,style=sketch +type: architecture +nodes: [ ... ] ``` +```` -Register it in `Program.cs`: +**Site-wide**, as the default for every fence via `BeckOptions.RenderOptions` (an individual +document's `meta.style` still opts back out): ```csharp -builder.Services.AddSingleton(); +builder.Services.AddPenningtonBeck(beck => +{ + beck.RenderOptions = new SvgRenderOptions { Style = BeckStyles.ByName["sketch"] }; +}); +``` + +Custom styles you register in `SvgRenderOptions.Styles` are addressable the same three ways — see +[Author a custom style](/docs/guides/custom-styles) and the +[style system reference](/docs/reference/styles) for resolution and precedence. + +## Measure with your site's own fonts + +By default Beck measures text against embedded Inter/IBM Plex Mono metrics, and every label carries +a `textLength` guard so a font mismatch squeezes glyphs slightly instead of breaking layout. If your +site renders diagrams in different fonts, cards drift a little tight or roomy — for anything you +publish, add the optional **`Beck.Skia`** package and point a `SkiaTextMeasurer` at the `.ttf` files +your CSS actually serves: + +```bash +dotnet add package Beck.Skia ``` -Now any ` ```beck ` fence in your Markdown renders to an inline SVG at build time. +```csharp +var font = new BeckFontSpec +{ + Family = "IBM Plex Sans", + MonoFamily = "IBM Plex Mono", + Files = new Dictionary + { + [400] = "wwwroot/fonts/IBMPlexSans-Regular.ttf", + [600] = "wwwroot/fonts/IBMPlexSans-SemiBold.ttf", + [700] = "wwwroot/fonts/IBMPlexSans-Bold.ttf", + }, + MonoFiles = new Dictionary { [400] = "wwwroot/fonts/IBMPlexMono-Regular.ttf" }, +}; -> [!IMPORTANT] -> **Measure with your site's own fonts.** The preprocessor above wires a `SkiaTextMeasurer` at the -> `.ttf` files your CSS serves, so Beck sizes each card to the text the browser will actually draw. -> `BeckSvg.Render(yaml)` also works with no measurer at all — a built-in default measures against -> Inter/IBM Plex Mono metrics — but if your site renders diagrams in different fonts, cards drift a -> little tight or roomy. Skia is the recommended setup for anything you publish. +builder.Services.AddPenningtonBeck(beck => +{ + beck.RenderOptions = new SvgRenderOptions + { + Font = font, + Measurer = new SkiaTextMeasurer(font), + }; +}); +``` ## Adopt your MonorailCSS palette @@ -130,9 +154,9 @@ render time. See [Match your theme and colours](/docs/guides/theme) for the full Because Pennington ships TreeSitter `:symbol` source embeds, you can keep a diagram's YAML in one `.beck.yaml` file and show both its source and its render from that single file — no duplication. -Pull the source with a `yaml:symbol` fence, then render the same file with a `beck:symbol` fence — -the preprocessor turns it into static SVG at build time. Add `,static` (`beck:symbol,static`) for a -still frame: +Pull the source with a `yaml:symbol` fence, then render the same file with a `beck:symbol` fence +(the body is one file path per line; each file renders independently). All the fence flags apply +(`beck:symbol,static`, `beck:symbol,style=sketch`): ````markdown ```yaml:symbol @@ -150,9 +174,33 @@ wwwroot/examples/guides/pennington-platform.beck.yaml wwwroot/examples/guides/pennington-platform.beck.yaml ``` +Paths resolve against `BeckOptions.ContentRoot`, which defaults to the working directory — set it to +match your TreeSitter `ContentRoot` so both `:symbol` forms address files the same way: + +```csharp +builder.Services.AddPenningtonBeck(beck => +{ + beck.ContentRoot = "../.."; +}); +``` + This is the convention these docs use throughout, showing each diagram's source beside the diagram itself. -Next, learn the language in [Your first diagram](/docs/tutorials/first-diagram), generate diagrams -from your model in [Generate diagrams from your code](/docs/guides/generate), or fine-tune colours in +## Fullscreen zoom + +Each rendered embed carries a zoom button that opens the diagram in a full-screen lightbox — the +package's one piece of client JavaScript; rendering stays server-side. Turn it off to emit bare SVG +with no client behavior: + +```csharp +builder.Services.AddPenningtonBeck(beck => +{ + beck.Zoom = false; +}); +``` + +Next, learn the language in [Your first diagram](/docs/tutorials/first-diagram), browse the looks in +[Pick a built-in style](/docs/guides/styles), generate diagrams from your model in +[Generate diagrams from your code](/docs/guides/generate), or fine-tune colours in [Match your theme and colours](/docs/guides/theme). diff --git a/docs/Beck.Docs/Content/docs/reference/yaml.md b/docs/Beck.Docs/Content/docs/reference/yaml.md index e665faa..07db933 100644 --- a/docs/Beck.Docs/Content/docs/reference/yaml.md +++ b/docs/Beck.Docs/Content/docs/reference/yaml.md @@ -45,6 +45,7 @@ the layered types — architecture, state, class.) | `subtitle` | string | — | Muted line under the title. | | `direction` | `TB` `BT` `LR` `RL` | `TB` | Primary layout axis: top-to-bottom, bottom-to-top, left-to-right, right-to-left. | | `theme` | `auto` `light` `dark` | `auto` | `auto` follows the host page. | +| `style` | string | `classic` | Visual style token — one of the nine built-ins (`classic`, `minimal`, `terminal`, `blueprint`, `glow`, `brutalist`, `sketch`, `extrude`, `circuit`) or a registered custom style. See [Pick a built-in style](/docs/guides/styles) and the [style system reference](/docs/reference/styles). | | `animate` | bool | `true` | `false` renders a static frame and never loads the motion runtime. | | `loop` | bool | `true` | `false` plays the flow once (forces `flow.repeat: 0`). | | `fit` | `shrink` `scroll` | `shrink` | What a diagram wider than its container does: `shrink` scales it down to fit; `scroll` keeps it at natural size and scrolls horizontally. Vertical size is never constrained. | diff --git a/docs/Beck.Docs/Content/for-ai.llms.md b/docs/Beck.Docs/Content/for-ai.llms.md index a59db79..ca294d2 100644 --- a/docs/Beck.Docs/Content/for-ai.llms.md +++ b/docs/Beck.Docs/Content/for-ai.llms.md @@ -75,6 +75,7 @@ field tables and defaults, see the [YAML schema reference](/docs/reference/yaml) | `title`, `subtitle` | string | — | | `direction` | `TB` `BT` `LR` `RL` | `TB` | | `theme` | `auto` `light` `dark` | `auto` (follows host page) | +| `style` | `classic` `minimal` `terminal` `blueprint` `glow` `brutalist` `sketch` `extrude` `circuit` (or a registered custom name) | `classic` | | `animate` | bool | `true` | | `loop` | bool | `true` (`false` plays once) | | `fit` | `shrink` `scroll` | `shrink` | @@ -352,9 +353,11 @@ Beck renders diagrams with the pure-C# engine — there is no client JS, no npm Two rendering paths: - **Fenced block (main path):** write a ` ```beck ` block (inline YAML) or a ` ```beck:symbol ` block - (pointing at a `.beck.yaml` file) in any Markdown page. The Pennington preprocessor runs the engine - at build time and inlines a static, self-animating `` — no script tag, no client runtime. Flag - variants force the static frame: ` ```beck,static ` and ` ```beck:symbol,static `. + (pointing at a `.beck.yaml` file) in any Markdown page. The `Pennington.Beck` package's + preprocessor runs the engine at build time and inlines a static, self-animating `` — no + script tag, no client runtime. Comma flags tune one fence: `,static` forces the still frame, + `,scrub` drives playback from scroll, and `,style=` overrides the document's `meta.style` + (they combine, e.g. ` ```beck:symbol,style=sketch,static `). - **C# / ASP.NET:** `BeckSvg.Render(yaml)` from the `Beck` package returns a self-contained `` string you write into a page (server-side or at build time). diff --git a/docs/Beck.Docs/wwwroot/js/site.js b/docs/Beck.Docs/wwwroot/js/site.js index 614419b..3649bd5 100644 --- a/docs/Beck.Docs/wwwroot/js/site.js +++ b/docs/Beck.Docs/wwwroot/js/site.js @@ -216,7 +216,7 @@ dialog.setAttribute('aria-label', 'Diagram, full screen'); var clone = svg.cloneNode(true); - // Drop the engine's inline sizing (max-width cap + height:auto) so the lightbox + // Drop the engine's inline sizing (max-width:100% + height:auto) so the lightbox // CSS controls the box: natural size from the width/height attributes, shrunk // proportionally only when it exceeds the viewport. clone.removeAttribute('style'); diff --git a/src/Beck/Svg/SvgRenderer.cs b/src/Beck/Svg/SvgRenderer.cs index 4f7d05e..744c1cd 100644 --- a/src/Beck/Svg/SvgRenderer.cs +++ b/src/Beck/Svg/SvgRenderer.cs @@ -228,9 +228,13 @@ public static string Render(DiagramModel model, ITextMeasurer measurer, string h animCss = "@media (prefers-reduced-motion:no-preference){" + motionCss + "}"; } + // meta.fit: `shrink` (default) lets the SVG scale down inside a narrow container + // (the width attribute already caps it at natural size in wide ones); `scroll` + // pins natural size so the host's overflow container scrolls instead. + var maxWidth = model.Meta.Fit == FitMode.Scroll ? $"{N(w)}px" : "100%"; var svg = new StringBuilder(); svg.Append($""); + .Append($"style=\"max-width:{maxWidth};height:auto\" font-family=\"var(--beck-font)\" role=\"img\" aria-label=\"{SvgWriter.Attr(model.Meta.Title ?? "diagram")}\">"); svg.Append(""); svg.Append("").Append(markers.Defs).Append(extraDefs).Append(animDefs).Append(edgeDefs).Append(Stylesheet.StyleDefs(hash, style)).Append(""); svg.Append(TitleBlock(model, w, style)); diff --git a/tests/Beck.Tests/Goldens/svg/class.svg b/tests/Beck.Tests/Goldens/svg/class.svg index c77b702..26de4ea 100644 --- a/tests/Beck.Tests/Goldens/svg/class.svg +++ b/tests/Beck.Tests/Goldens/svg/class.svg @@ -1 +1 @@ -Order Model1**1placed byraises«abstract»EntityId: GuidCreatedAt: DateTimeOffset«aggregate»OrderStatus: OrderStatusTotal: MoneyAddLine(sku, qty)Submit()OrderLineSku: stringQty: intPrice: MoneyCustomerName: stringEmail: stringDeactivate()«interface»IOrderNotifierOrderPlaced(order) \ No newline at end of file +Order Model1**1placed byraises«abstract»EntityId: GuidCreatedAt: DateTimeOffset«aggregate»OrderStatus: OrderStatusTotal: MoneyAddLine(sku, qty)Submit()OrderLineSku: stringQty: intPrice: MoneyCustomerName: stringEmail: stringDeactivate()«interface»IOrderNotifierOrderPlaced(order) \ No newline at end of file diff --git a/tests/Beck.Tests/Goldens/svg/seq-kitchen.svg b/tests/Beck.Tests/Goldens/svg/seq-kitchen.svg index 63cc123..acbfd3b 100644 --- a/tests/Beck.Tests/Goldens/svg/seq-kitchen.svg +++ b/tests/Beck.Tests/Goldens/svg/seq-kitchen.svg @@ -1 +1 @@ -CheckoutBROWSENOTIFYDONEclickPOST /orderinsertok201emailUserWebapidbuser clicks buy \ No newline at end of file +CheckoutBROWSENOTIFYDONEclickPOST /orderinsertok201emailUserWebapidbuser clicks buy \ No newline at end of file diff --git a/tests/Beck.Tests/RenderSmokeTests.cs b/tests/Beck.Tests/RenderSmokeTests.cs index 7f334e8..a70421b 100644 --- a/tests/Beck.Tests/RenderSmokeTests.cs +++ b/tests/Beck.Tests/RenderSmokeTests.cs @@ -29,6 +29,27 @@ public void RenderCorpusToFiles() } } + [Fact] + public void FitModeControlsInlineMaxWidth() + { + const string nodes = """ + nodes: + - { id: a, title: Node A } + - { id: b, title: Node B } + edges: + - { from: a, to: b } + """; + + // Default (shrink): responsive — scales down inside a narrow container. + var shrink = BeckSvg.Render(nodes); + Assert.Contains("style=\"max-width:100%;height:auto\"", shrink); + + // fit: scroll pins natural size (the width attribute's value) so the host scrolls. + var scroll = BeckSvg.Render("meta:\n fit: scroll\n" + nodes); + Assert.DoesNotContain("max-width:100%", scroll); + Assert.Matches("style=\"max-width:[0-9.]+px;height:auto\"", scroll); + } + [Fact] public void ScrubModeDrivesAnimationsOffTheViewTimeline() { diff --git a/tools/oracle/rendered/arch-flow.svg b/tools/oracle/rendered/arch-flow.svg index b5df1f4..c3ebf0f 100644 --- a/tools/oracle/rendered/arch-flow.svg +++ b/tools/oracle/rendered/arch-flow.svg @@ -1 +1 @@ -Credential RequestA request travels out and the credential returnsbuild.shidleget_credential()aac connectPairs with deviceRemoteClientOpens the tunnelProxyBitwardenreadybuild.sh needs a secret, so it asks theCLI to fetch one.The SDK opens a tunnel and relays therequest through the zero-knowledge proxy.Bitwarden approves and streams thecredential back down the same path. \ No newline at end of file +Credential RequestA request travels out and the credential returnsbuild.shidleget_credential()aac connectPairs with deviceRemoteClientOpens the tunnelProxyBitwardenreadybuild.sh needs a secret, so it asks theCLI to fetch one.The SDK opens a tunnel and relays therequest through the zero-knowledge proxy.Bitwarden approves and streams thecredential back down the same path. \ No newline at end of file diff --git a/tools/oracle/rendered/arch-grouped.svg b/tools/oracle/rendered/arch-grouped.svg index 3cb179f..8d9be70 100644 --- a/tools/oracle/rendered/arch-grouped.svg +++ b/tools/oracle/rendered/arch-grouped.svg @@ -1 +1 @@ -Web PlatformGateway fan-out into grouped services and storesWeb AppBrowser SPAAPI GatewayRouting + authAuth ServiceCatalog ServiceOrders ServiceAuth DBCatalog DBEventsMessage busSERVICESDATA STORES \ No newline at end of file +Web PlatformGateway fan-out into grouped services and storesWeb AppBrowser SPAAPI GatewayRouting + authAuth ServiceCatalog ServiceOrders ServiceAuth DBCatalog DBEventsMessage busSERVICESDATA STORES \ No newline at end of file diff --git a/tools/oracle/rendered/arch-simple.svg b/tools/oracle/rendered/arch-simple.svg index 521981c..9ac6e8b 100644 --- a/tools/oracle/rendered/arch-simple.svg +++ b/tools/oracle/rendered/arch-simple.svg @@ -1 +1 @@ -Request PathA minimal three-tier flowqueryBrowserAPI ServerHandles requestsPostgres \ No newline at end of file +Request PathA minimal three-tier flowqueryBrowserAPI ServerHandles requestsPostgres \ No newline at end of file diff --git a/tools/oracle/rendered/class.svg b/tools/oracle/rendered/class.svg index 3505d1e..3745998 100644 --- a/tools/oracle/rendered/class.svg +++ b/tools/oracle/rendered/class.svg @@ -1 +1 @@ -Order Model1**1placed byraises«abstract»EntityId: GuidCreatedAt: DateTimeOffset«aggregate»OrderStatus: OrderStatusTotal: MoneyAddLine(sku, qty)Submit()OrderLineSku: stringQty: intPrice: MoneyCustomerName: stringEmail: stringDeactivate()«interface»IOrderNotifierOrderPlaced(order) \ No newline at end of file +Order Model1**1placed byraises«abstract»EntityId: GuidCreatedAt: DateTimeOffset«aggregate»OrderStatus: OrderStatusTotal: MoneyAddLine(sku, qty)Submit()OrderLineSku: stringQty: intPrice: MoneyCustomerName: stringEmail: stringDeactivate()«interface»IOrderNotifierOrderPlaced(order) \ No newline at end of file diff --git a/tools/oracle/rendered/sample-architecture.svg b/tools/oracle/rendered/sample-architecture.svg index aa6d44d..eff7734 100644 --- a/tools/oracle/rendered/sample-architecture.svg +++ b/tools/oracle/rendered/sample-architecture.svg @@ -1 +1 @@ -Web PlatformGenerated by Beck.AuthoringWeb AppBrowser SPAGET /ordersAPI GatewayRouting + authAuth ServiceCatalog ServiceOrders ServiceAuth DBCatalog DBEventsMessage busSERVICESDATA STORESrequest \ No newline at end of file +Web PlatformGenerated by Beck.AuthoringWeb AppBrowser SPAGET /ordersAPI GatewayRouting + authAuth ServiceCatalog ServiceOrders ServiceAuth DBCatalog DBEventsMessage busSERVICESDATA STORESrequest \ No newline at end of file diff --git a/tools/oracle/rendered/sample-sequence.svg b/tools/oracle/rendered/sample-sequence.svg index ed49288..6d351aa 100644 --- a/tools/oracle/rendered/sample-sequence.svg +++ b/tools/oracle/rendered/sample-sequence.svg @@ -1 +1 @@ -CheckoutGenerated by Beck.AuthoringPAYMENTPERSISTPOST /ordersvalidate cartcapturecapturedINSERT orderok201 CreatedWeb AppOrders APIPaymentsPostgres \ No newline at end of file +CheckoutGenerated by Beck.AuthoringPAYMENTPERSISTPOST /ordersvalidate cartcapturecapturedINSERT orderok201 CreatedWeb AppOrders APIPaymentsPostgres \ No newline at end of file diff --git a/tools/oracle/rendered/seq-kitchen.svg b/tools/oracle/rendered/seq-kitchen.svg index 65c370e..92c2aa0 100644 --- a/tools/oracle/rendered/seq-kitchen.svg +++ b/tools/oracle/rendered/seq-kitchen.svg @@ -1 +1 @@ -CheckoutBROWSENOTIFYDONEclickPOST /orderinsertok201emailUserWebapidbuser clicks buy \ No newline at end of file +CheckoutBROWSENOTIFYDONEclickPOST /orderinsertok201emailUserWebapidbuser clicks buy \ No newline at end of file diff --git a/tools/oracle/rendered/sequence.svg b/tools/oracle/rendered/sequence.svg index 5aec7ac..c9a3049 100644 --- a/tools/oracle/rendered/sequence.svg +++ b/tools/oracle/rendered/sequence.svg @@ -1 +1 @@ -CheckoutOrder placement with payment capturePAYMENTPERSIST & PUBLISHPOST /ordersvalidate cartcapturecapturedINSERT orderokOrderPlaced201 CreatedWeb AppOrders APIPaymentsPostgresEventsThe shopper submits their cart to the Orders API.The API asks the payment service to capture funds.With payment secured, the order is written to Postgres.An OrderPlaced event fans out to downstream subscribers. \ No newline at end of file +CheckoutOrder placement with payment capturePAYMENTPERSIST & PUBLISHPOST /ordersvalidate cartcapturecapturedINSERT orderokOrderPlaced201 CreatedWeb AppOrders APIPaymentsPostgresEventsThe shopper submits their cart to the Orders API.The API asks the payment service to capture funds.With payment secured, the order is written to Postgres.An OrderPlaced event fans out to downstream subscribers. \ No newline at end of file diff --git a/tools/oracle/rendered/state.svg b/tools/oracle/rendered/state.svg index b54255c..972e454 100644 --- a/tools/oracle/rendered/state.svg +++ b/tools/oracle/rendered/state.svg @@ -1 +1 @@ -Order LifecyclesubmitrejectapproveretractdraftIn ReviewPublished \ No newline at end of file +Order LifecyclesubmitrejectapproveretractdraftIn ReviewPublished \ No newline at end of file