Class ConsoleChromeMixin
/juneau-console/chrome.css.
Compose into a host resource via @Rest(mixins=ConsoleChromeMixin.class) (see
DataTablesMixin in the juneau-console-datatables module for the identical asset-serving
pattern this mirrors — not linked here since that module is not a dependency of this one). The served
response is the static
structural chrome.css (shipped in this module's classpath) with Theme.OPEN's block, then the
selected stock theme's override block if one other than open was selected, appended as
html:root{} blocks.
Mount styles:
Both of the following arrangements serve the stylesheets at the CHROME_CSS_PATH / THEME_CSS_DIR
URLs with no path juggling by the host resource:
- Composed — the host resource is mounted wherever the application already mounts it (e.g.
/rest/*) and the stylesheets hang off that mount, at<host-mount>/juneau-console/chrome.css. - Standalone — the host resource is registered with the servlet container at url-pattern
/juneau-console/*so the stylesheets sit at a fixed site-root URL, independent of which page or tab rendered the referencing<link>.
The two arrangements need different operation paths, because a container mount at /juneau-console/*
reports servletPath="/juneau-console" and Juneau resolves an operation's path against the request URI
with contextPath + servletPath already removed — leaving only /chrome.css to match.
Each operation below therefore declares both its prefixed path and the same path minus the
/juneau-console prefix, so whichever one the arrangement leaves to be matched resolves.
Theme precedence
ConsoleChromeMixin.Builder.theme(String) if set, else Theme.OPEN. Theme.OPEN's block is always appended
first; a selected non-open stock theme adds exactly one more block.
Stylesheet load-order band:
At equal cascade specificity, whichever of juneau-views.css and this class's chrome.css is
declared later in a page's <head> wins — the exact ambiguity the overrideBlock theme block
below is raised to html:root to make irrelevant. Juneau's own in-tree page emitters (the examples
module) don't rely on that fix alone: they declare a five-position stylesheet/script load-order band,
enforced by a build-time test, so their own asset order is never left to chance in the first place:
- vendor stylesheets
juneau-views.css— the views base layer- first-party widget stylesheets that build on the views layer, e.g.
juneau-calendar.css - the consumer theme, e.g. this class's
chrome.css - page-local
<style>
That guard reaches only the pages Juneau itself emits. It says nothing about, and claims no control over, an
arbitrary host application's own document — a consumer is free to link chrome.css and
juneau-views.css in either order, which is precisely why the html:root fix exists: so the
active theme wins regardless of which order the consumer's links happen to appear in.
Example:
Custom palettes aren't configured here. Author them in the FreeMarker chrome with <@theme>/<@token>
(see the Theme example), which emits the stock-theme <link> plus an inline override block.
- Since:
- 10.0.0
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classBuilder forConsoleChromeMixin.static final recordThe two head insertion points for a colour-scheme-aware page. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringContext-root-absolute path of the count-badge script.static final StringBADGES_JS_PATHminus the/juneau-consoleprefix.static final StringClasspath location of the count-badge script.The built-in stock-theme names - the kebab-case of theThemeconstants (Theme.OPEN,Theme.LIGHT_RED,Theme.LIGHT_BROWN,Theme.RED,Theme.GRAY).static final StringContext-root-absolute path of the chart-card runtime.static final StringCHARTS_JS_PATHminus the/juneau-consoleprefix.static final StringClasspath location of the chart-card runtime.static final StringThe URL path at which the chrome stylesheet is served (relative to the host mount).static final StringContext-root-absolute path of the console shell script.static final StringCONSOLE_JS_PATHminus the/juneau-consoleprefix - see the class javadoc's mount-styles section.static final StringClasspath location of the console shell script.static final StringContext-root-absolute path of the dashboard chrome runtime.static final StringDASHBOARD_JS_PATHminus the/juneau-consoleprefix.static final StringClasspath resource behindDASHBOARD_JS_PATH.static final StringContext-root-absolute path of the job-log card runtime.static final StringJOBLOG_JS_PATHminus the/juneau-consoleprefix.static final StringClasspath location of the job-log card runtime.static final StringContext-root-absolute path of the page-contract schema.static final StringThe inline pre-paint script that picks the page's colour scheme before first paint.static final StringThe CSP source expression forSCHEME_SCRIPT:'sha256-<base64>'over its UTF-8 bytes.The colour-scheme pin values, in documented order.static final StringThe URL directory the shipped stock-theme stylesheets are served under (relative to the host mount), e.g. -
Constructor Summary
ConstructorsModifierConstructorDescriptionNo-arg constructor, mirroringFreemarkerMixin()'s equivalent so a bean-store lookup miss can fall back to a default-configured instance without relying onBeanInstantiator's builder-pattern detection.protectedConstructor. -
Method Summary
Modifier and TypeMethodDescriptionstatic StringbadgesJsUrl(RestRequest req) Context-root-absolute, cache-busted URL of the count-badge script.static StringchromeCssUrl(RestRequest req) Returns a real, browser-fetchable URL for the shippedchrome.css, resolved against the request's context root (not the page resource) and carrying the same content-sensitive?v=…cache-buster the theme stylesheets use.static StringconsoleAssetUrl(RestRequest req, String path) Context-root-absolute, cache-busted URL of a console card runtime; the resolver of thechartsandjoblogtoolkit packs.static StringconsoleJsUrl(RestRequest req) Context-root-absolute, cache-busted URL of the console shell script.static ConsoleChromeMixin.Buildercreate()Creates a new builder.[GET /juneau-console/juneau-badges.js] — serve the count-badge script.[GET /juneau-console/juneau-charts.js] — serve the chart-card runtime.getChromeCss(RestRequest req) [GET /juneau-console/chrome.css] — serve the admin-console chrome stylesheet.[GET /juneau-console/juneau-console.js] — serve the console shell.[GET /juneau-console/juneau-dashboard.js] — serve the dashboard chrome runtime.[GET /juneau-console/juneau-joblog.js] — serve the job-log card runtime.[GET /juneau-console/juneau-page.schema.json] — serve the page-contract schema.getThemeCss(String file) [GET /juneau-console/themes/{file}] — serve one of the shipped stock-theme stylesheets.static StringReturnsnonce="…"(with a leading space, attribute-escaped) or an empty string fornull .static StringoverrideBlock(Theme theme) Renders a theme's override block: onehtml:root{...}carrying the theme's leaf tokens, then its alias tokens, each in declaration order.Returns the names of the role aliases the chrome declares, such as--jc-surface,--jc-danger-textand--jc-header-bg.schemeHead(RestRequest req, String pin, boolean toggle) Returns the colour-scheme head pieces for a page that does not render through the FreeMarker console directive.static StringschemeHtmlAttributes(String pin, boolean toggle) Returns the<html>start-tag attributes for a scheme pin and toggle flag.static StringRenders the dark-scheme override rule for app-declared dark tokens.static StringschemeScriptElement(String nonce) static ThemestockTheme(String name) Maps one of theBUILTIN_THEME_NAMESstock names to itsThemeconstant.static StringthemeAssetUrl(RestRequest req, String name) Returns a real, browser-fetchable URL for a shipped theme stylesheet, resolved against the request's context root (not the page resource) and carrying the same?v=<buildVersion>-<hash8>content-sensitive cache-busterchromeCssUrl(RestRequest)uses.
-
Field Details
-
CHROME_CSS_PATH
The URL path at which the chrome stylesheet is served (relative to the host mount).- See Also:
-
THEME_CSS_DIR
The URL directory the shipped stock-theme stylesheets are served under (relative to the host mount), e.g./juneau-console/themes/juneau-theme-light-red.css. A subdirectory of the chrome mount so a templated{file}path cannot collide with the fixedCHROME_CSS_PATHendpoint. The FTL<@theme name="…"/>directive links these; seethemeAssetUrl(RestRequest, String).- See Also:
-
BUILTIN_THEME_NAMES
The built-in stock-theme names - the kebab-case of theThemeconstants (Theme.OPEN,Theme.LIGHT_RED,Theme.LIGHT_BROWN,Theme.RED,Theme.GRAY). Each maps to a shippedjuneau-theme-<name>.cssstylesheet. Consumed by the FTL<@theme>directive to fail an unknown name closed, and here to bound the served{file}to a known stock theme. -
SCHEMES
The colour-scheme pin values, in documented order.auto(the default) follows the browser'sprefers-color-scheme;lightanddarkpin the page to that scheme. Accepted by<@console scheme="…">,PageSpec.scheme(String)andschemeHead(RestRequest, String, boolean). -
SCHEME_SCRIPT
The inline pre-paint script that picks the page's colour scheme before first paint.It sets
data-jc-schemeon the root element from, in order: the visitor's stored choice (only when the root carriesdata-jc-scheme-toggle), the server pin (data-jc-scheme-pin), then the browser'sprefers-color-scheme. It never throws: storage and media-query failures fall through to the next source, ending atlight.The text is a byte-for-byte constant so
SCHEME_SCRIPT_CSP_HASHis stable. Emit it as the first child of<head>, ahead of every stylesheet. -
SCHEME_SCRIPT_CSP_HASH
The CSP source expression forSCHEME_SCRIPT:'sha256-<base64>'over its UTF-8 bytes.Add it to a
script-srcdirective to allow the pre-paint script without a nonce. It covers only the script. The console shell's inline<style>(theme override blocks) still needs the request nonce or'unsafe-inline'instyle-src. -
CONSOLE_JS_PATH
Context-root-absolute path of the console shell script.- See Also:
-
CONSOLE_JS_PATH_UNPREFIXED
CONSOLE_JS_PATHminus the/juneau-consoleprefix - see the class javadoc's mount-styles section.- See Also:
-
CONSOLE_JS_RESOURCE
Classpath location of the console shell script.- See Also:
-
BADGES_JS_PATH
Context-root-absolute path of the count-badge script.- See Also:
-
BADGES_JS_PATH_UNPREFIXED
BADGES_JS_PATHminus the/juneau-consoleprefix.- See Also:
-
BADGES_JS_RESOURCE
Classpath location of the count-badge script.- See Also:
-
CHARTS_JS_PATH
Context-root-absolute path of the chart-card runtime.- See Also:
-
CHARTS_JS_PATH_UNPREFIXED
CHARTS_JS_PATHminus the/juneau-consoleprefix.- See Also:
-
CHARTS_JS_RESOURCE
Classpath location of the chart-card runtime.- See Also:
-
JOBLOG_JS_PATH
Context-root-absolute path of the job-log card runtime.- See Also:
-
JOBLOG_JS_PATH_UNPREFIXED
JOBLOG_JS_PATHminus the/juneau-consoleprefix.- See Also:
-
JOBLOG_JS_RESOURCE
Classpath location of the job-log card runtime.- See Also:
-
DASHBOARD_JS_PATH
Context-root-absolute path of the dashboard chrome runtime.- See Also:
-
DASHBOARD_JS_PATH_UNPREFIXED
DASHBOARD_JS_PATHminus the/juneau-consoleprefix.- See Also:
-
DASHBOARD_JS_RESOURCE
Classpath resource behindDASHBOARD_JS_PATH.- See Also:
-
SCHEMA_PATH
Context-root-absolute path of the page-contract schema.- See Also:
-
-
Constructor Details
-
ConsoleChromeMixin
public ConsoleChromeMixin()No-arg constructor, mirroringFreemarkerMixin()'s equivalent so a bean-store lookup miss can fall back to a default-configured instance without relying onBeanInstantiator's builder-pattern detection. -
ConsoleChromeMixin
Constructor.- Parameters:
builder- The builder.
-
-
Method Details
-
roleAliasNames
Returns the names of the role aliases the chrome declares, such as--jc-surface,--jc-danger-textand--jc-header-bg.These are the custom properties the chrome derives from the
Theme.OPENtokens. They are not tokens of anyTheme, but a page resolves them at run time, so the FreeMarker<@token scheme="dark">alias check accepts them as targets.- Returns:
- An unmodifiable set of custom-property names; never
null .
-
create
Creates a new builder.- Returns:
- A new builder.
-
getChromeCss
[GET /juneau-console/chrome.css] — serve the admin-console chrome stylesheet.- Parameters:
req- The current request, used to key the per-mount body cache.- Returns:
- The chrome stylesheet as a CSS
HttpResource. - Throws:
IOException- If the shippedchrome.cssresource could not be read (effectively unreachable — the resource is shipped in the same jar as this class).
-
getThemeCss
[GET /juneau-console/themes/{file}] — serve one of the shipped stock-theme stylesheets.The
{file}segment is fail-closed to the knownBUILTIN_THEME_NAMESstylesheet filenames, so this endpoint can never read an arbitrary classpath resource. Each stylesheet is a structure-freehtml:root{}token block (one perThemeconstant); the FTL<@theme name="…"/>directive links the winning one afterchrome.cssso its tokens overridechrome.css's baked-inTheme.OPENblock.- Parameters:
file- The requested stylesheet filename (e.g.juneau-theme-light-red.css).- Returns:
- The theme stylesheet as a CSS
HttpResource. - Throws:
NotFound- Iffileis not one of the shipped stylesheet filenames.
-
getConsoleJs
[GET /juneau-console/juneau-console.js] — serve the console shell.- Returns:
- The script.
-
getBadgesJs
[GET /juneau-console/juneau-badges.js] — serve the count-badge script.- Returns:
- The script.
-
getChartsJs
[GET /juneau-console/juneau-charts.js] — serve the chart-card runtime.- Returns:
- The script.
-
getJobLogJs
[GET /juneau-console/juneau-joblog.js] — serve the job-log card runtime.- Returns:
- The script.
-
getDashboardJs
[GET /juneau-console/juneau-dashboard.js] — serve the dashboard chrome runtime.- Returns:
- The script.
-
getPageSchema
[GET /juneau-console/juneau-page.schema.json] — serve the page-contract schema.- Returns:
- The schema.
-
themeAssetUrl
Returns a real, browser-fetchable URL for a shipped theme stylesheet, resolved against the request's context root (not the page resource) and carrying the same?v=<buildVersion>-<hash8>content-sensitive cache-busterchromeCssUrl(RestRequest)uses.The console document shell (
<@console>/<@theme>) emits this as a<link href>to the standalone/juneau-console/*mount. Resolving withcontext:rather thanservlet:is load-bearing: a page resource at/rest/setupreports that path as its servlet path, soservlet:/juneau-console/themes/…would become/rest/setup/juneau-console/themes/…and 404. A template-rendering consumer sits downstream of Juneau'sservlet:-rewriting serializer, so it needs the URL already resolved here.- Parameters:
req- The current request, supplying the context path to resolve against.name- One of theBUILTIN_THEME_NAMES.- Returns:
- The context-root-absolute theme-stylesheet URL with the version+content-hash cache-buster appended.
-
chromeCssUrl
Returns a real, browser-fetchable URL for the shippedchrome.css, resolved against the request's context root (not the page resource) and carrying the same content-sensitive?v=…cache-buster the theme stylesheets use.The console document shell (
<@console>) emits this as the first stylesheet in its head cascade. SeethemeAssetUrl(RestRequest, String)for why the resolution iscontext:rather thanservlet:.- Parameters:
req- The current request, supplying the context path to resolve against.- Returns:
- The context-root-absolute
chrome.cssURL with the version+content-hash cache-buster appended.
-
consoleJsUrl
Context-root-absolute, cache-busted URL of the console shell script.- Parameters:
req- The current request.- Returns:
- The URL.
-
badgesJsUrl
Context-root-absolute, cache-busted URL of the count-badge script.- Parameters:
req- The current request.- Returns:
- The URL.
-
consoleAssetUrl
Context-root-absolute, cache-busted URL of a console card runtime; the resolver of thechartsandjoblogtoolkit packs.- Parameters:
req- The current request.path-CHARTS_JS_PATH,JOBLOG_JS_PATHorDASHBOARD_JS_PATH.- Returns:
- The URL.
- Throws:
IllegalArgumentException- Ifpathis neither.
-
stockTheme
Maps one of theBUILTIN_THEME_NAMESstock names to itsThemeconstant.The single place the kebab-case stock name (as written on FTL
<@theme name="…">/ thetheme(String)builder) is resolved to its shippedTheme, without a second copy of the name→theme table.- Parameters:
name- One of theBUILTIN_THEME_NAMES.- Returns:
- The stock
Themeforname. - Throws:
IllegalArgumentException- Ifnameis not a built-in stock-theme name.
-
overrideBlock
Renders a theme's override block: onehtml:root{...}carrying the theme's leaf tokens, then its alias tokens, each in declaration order.The two halves are escaped differently. A leaf is a validated literal and goes through
CssValueEscaper: a grammar-accepted value can still carry a character such as;that would end the declaration early. An alias is a single anchoredvar(--jc-name)reference (Theme.Builder.alias(String, String)), in which nothing dangerous is representable, so it is emitted verbatim. That asymmetry is the reasonTheme.getAliases()stays a map.The block uses the
htmltype prefix. Two:rootblocks in separately linked stylesheets tie at specificity(0,0,1,0)and are resolved by<link>order, which this framework neither sets nor observes.html:rootscores(0,0,1,1), so a theme override wins in either order.A theme with no leaves and no aliases renders as the empty string. Each declared name is re-checked against the reserved
--jc-chrome-*namespace (defense in depth; aThemebuilt by its builder can't carry one). This method is public so the FreeMarker<@theme>directive renders its inline block with the same code that serveschrome.css.Example:
Theme
theme = Theme.create ("corporate" ) .token("--jc-accent" ,"#b45309" ) .alias("--jc-tab-bar-bg" ,"var(--jc-card-bg)" ) .build(); Stringcss = ConsoleChromeMixin.overrideBlock (theme );// html:root{--jc-accent:#b45309;--jc-tab-bar-bg:var(--jc-card-bg);} - Parameters:
theme- The theme. Must not benull .- Returns:
- The override block, or an empty string if the theme declares nothing.
-
schemeHead
Returns the colour-scheme head pieces for a page that does not render through the FreeMarker console directive.A pinned page (
lightordark) getsdata-jc-schemeanddata-jc-scheme-pinset to the pin, so it paints in that scheme even with scripts disabled. A toggleable page getsdata-jc-scheme-toggle, which lets the pre-paint script honour the visitor's stored choice. The head piece isSCHEME_SCRIPT(stamped with the request's CSP nonce when one is set) followed by a link to the shipped dark layer.Example:
SchemeHead
h = ConsoleChromeMixin.schemeHead (req ,"auto" ,true );var attrs =h .htmlAttributes().isEmpty() ?"" :" " +h .htmlAttributes();out .write("<html lang=\"en\"" +attrs +"><head>" +h .head());The head piece carries only the scheme script and the dark layer. It does not replace the page's own links to the chrome stylesheet and a theme palette, which the caller still emits.
- Parameters:
req- The current request, supplying the context path and any CSP nonce.pin- One of theSCHEMES.toggle- Whether the visitor may override the scheme with a stored choice.- Returns:
- The head pieces.
- Throws:
IllegalArgumentException- Ifpinisnull or not one of theSCHEMES.
-
schemeHtmlAttributes
Returns the<html>start-tag attributes for a scheme pin and toggle flag.The FreeMarker console directive and
schemeHead(RestRequest, String, boolean)share this so the two shells stamp identical attributes.- Parameters:
pin- One of theSCHEMES.toggle- Whether the visitor may override the scheme with a stored choice.- Returns:
- The attributes, space-separated with no leading space, or an empty string.
- Throws:
IllegalArgumentException- Ifpinisnull or not one of theSCHEMES.
-
schemeScriptElement
- Parameters:
nonce- The request's CSP nonce, ornull .- Returns:
- The
<script>element, with no trailing newline.
-
nonceAttr
Returnsnonce="…"(with a leading space, attribute-escaped) or an empty string fornull .- Parameters:
nonce- The request's CSP nonce, ornull .- Returns:
- The attribute text.
-
schemeOverrideBlock
Renders the dark-scheme override rule for app-declared dark tokens.The rule is
@media not print{html:root[data-jc-scheme="dark"]{…}}, so it wins over the light override block only while the page is dark and never reaches print. Leaves come first, then aliases, each in declaration order. A leaf must be a literal: a dark leaf that is itself avar()reference is rejected, because it would resolve against the light palette. A live link belongs in an alias. Names and values get the same checks asTheme.Builder: the name shape, the reserved--jc-chrome-*namespace, the value grammar, and one channel per name.Example:
String
css = ConsoleChromeMixin.schemeOverrideBlock ( Map.of ("--jc-link" ,"#6cb4ff" ), Map.of ("--jc-focus" ,"var(--jc-accent)" ));// @media not print{html:root[data-jc-scheme="dark"]{--jc-link:#6cb4ff;--jc-focus:var(--jc-accent);}} - Parameters:
tokens- The dark leaf tokens by name. Must not benull .aliases- The dark aliases by name, each avar(--jc-name)reference. Must not benull .- Returns:
- The rule, or an empty string if both maps are empty.
- Throws:
IllegalArgumentException- If a name or value fails validation.
-