Skip to content

Commit a496e0e

Browse files
no flashing when reloading in light or dark mode
fixes #1325 introduces a new script before the body which runs immediately, enabling or disabling dark mode both stylesheets are loaded, one is disabled in JS the default stylesheet is loaded second, in case JS is disabled
1 parent 1abab5b commit a496e0e

File tree

6 files changed

+913
-879
lines changed

6 files changed

+913
-879
lines changed

news/changelog-1.7.md

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ All changes included in 1.7:
4545

4646
- ([#12277](https://github.com/quarto-dev/quarto-cli/pull/12277)): Provide light and dark plot and table renderings with `renderings: [light,dark]`
4747
- ([#11860](https://github.com/quarto-dev/quarto-cli/issues/11860)): ES6 modules that import other local JS modules in documents with `embed-resources: true` are now correctly embedded.
48+
- ([#1325](https://github.com/quarto-dev/quarto-cli/issues/1325)): Dark Mode pages should not flash light on reload. (Nor should Light Mode pages flash dark.)
4849

4950
## `pdf` format
5051

src/command/render/pandoc-html.ts

+27-15
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ export async function resolveSassBundles(
130130
// Note that the other bundle provides light
131131
targets[0].attribs = {
132132
...targets[0].attribs,
133-
...attribForThemeStyle("light", defaultStyle),
133+
...attribForThemeStyle("light"),
134134
};
135135

136136
// Provide a dark bundle for this
@@ -144,14 +144,19 @@ export async function resolveSassBundles(
144144
bundle.key = bundle.key + "-dark";
145145
return bundle;
146146
});
147-
targets.push({
147+
const darkTarget = {
148148
name: `${dependency}-dark.min.css`,
149149
bundles: darkBundles as any,
150150
attribs: {
151151
"append-hash": "true",
152-
...attribForThemeStyle("dark", defaultStyle),
152+
...attribForThemeStyle("dark"),
153153
},
154-
});
154+
};
155+
if (defaultStyle === "dark") {
156+
targets.push(darkTarget);
157+
} else {
158+
targets.unshift(darkTarget);
159+
}
155160

156161
hasDarkStyles = true;
157162
}
@@ -256,6 +261,18 @@ export async function resolveSassBundles(
256261
}
257262

258263
// Resolve generated quarto css variables
264+
if (hasDarkStyles && defaultStyle !== "dark") {
265+
// Put dark stylesheet first if light is default (for NoJS)
266+
extras = await resolveQuartoSyntaxHighlighting(
267+
inputDir,
268+
extras,
269+
format,
270+
project,
271+
"dark",
272+
defaultStyle,
273+
);
274+
}
275+
259276
extras = await resolveQuartoSyntaxHighlighting(
260277
inputDir,
261278
extras,
@@ -265,8 +282,8 @@ export async function resolveSassBundles(
265282
defaultStyle,
266283
);
267284

268-
if (hasDarkStyles) {
269-
// Provide dark variables for this
285+
if (hasDarkStyles && defaultStyle === "dark") {
286+
// Put dark stylesheet second if dark is default (for NoJS)
270287
extras = await resolveQuartoSyntaxHighlighting(
271288
inputDir,
272289
extras,
@@ -303,7 +320,7 @@ async function resolveQuartoSyntaxHighlighting(
303320
extras = cloneDeep(extras);
304321

305322
// If we're using default highlighting, use theme darkness to select highlight style
306-
const mediaAttr = attribForThemeStyle(style, defaultStyle);
323+
const mediaAttr = attribForThemeStyle(style);
307324
if (style === "default") {
308325
if (extras.html?.[kTextHighlightingMode] === "dark") {
309326
style = "dark";
@@ -559,28 +576,23 @@ const kVariablesRegex =
559576
/\/\*\! quarto-variables-start \*\/([\S\s]*)\/\*\! quarto-variables-end \*\//g;
560577

561578
// Attributes for the style tag
562-
// Note that we default disable the dark mode and rely on JS to enable it
563579
function attribForThemeStyle(
564580
style: "dark" | "light" | "default",
565-
defaultStyle?: "dark" | "light",
566581
): Record<string, string> {
567-
const colorModeAttrs = (mode: string, disabled: boolean) => {
582+
const colorModeAttrs = (mode: string) => {
568583
const attr: Record<string, string> = {
569584
class: `quarto-color-scheme${
570585
mode === "dark" ? " quarto-color-alternate" : ""
571586
}`,
572587
};
573-
if (disabled) {
574-
attr.rel = "prefetch";
575-
}
576588
return attr;
577589
};
578590

579591
switch (style) {
580592
case "dark":
581-
return colorModeAttrs("dark", defaultStyle !== "dark");
593+
return colorModeAttrs("dark");
582594
case "light":
583-
return colorModeAttrs("light", false);
595+
return colorModeAttrs("light");
584596
case "default":
585597
default:
586598
return {};

src/format/html/format-html.ts

+18-11
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
kFigResponsive,
2525
kFilterParams,
2626
kHeaderIncludes,
27+
kIncludeBeforeBody,
2728
kIncludeAfterBody,
2829
kIncludeInHeader,
2930
kLinkExternalFilter,
@@ -501,28 +502,33 @@ export async function htmlFormatExtras(
501502
renderEjs(
502503
formatResourcePath("html", join("hypothesis", "hypothesis.ejs")),
503504
{ hypothesis: options.hypothesis },
504-
),
505+
)
505506
);
506507
includeInHeader.push(hypothesisHeader);
507508
}
508509

509-
// after body
510+
// before and after body
511+
const includeBeforeBody: string[] = [];
510512
const includeAfterBody: string[] = [];
511513

512514
// add main orchestion script if we have any options enabled
513515
const quartoHtmlRequired = Object.keys(options).some((option) =>
514516
!!options[option]
515517
);
516518
if (quartoHtmlRequired) {
517-
// html orchestration script
518-
const quartoHtmlScript = temp.createFile();
519-
const renderedHtml = renderEjs(
520-
formatResourcePath("html", join("templates", "quarto-html.ejs")),
521-
options,
522-
);
523-
if (renderedHtml.trim() !== "") {
524-
Deno.writeTextFileSync(quartoHtmlScript, renderedHtml);
525-
includeAfterBody.push(quartoHtmlScript);
519+
for(const {dest, ejsfile} of [
520+
{dest: includeBeforeBody, ejsfile: "quarto-html-before-body.ejs"},
521+
{dest: includeAfterBody, ejsfile: "quarto-html-after-body.ejs"}
522+
]) {
523+
const quartoHtmlScript = temp.createFile();
524+
const renderedHtml = renderEjs(
525+
formatResourcePath("html", join("templates", ejsfile)),
526+
options,
527+
);
528+
if (renderedHtml.trim() !== "") {
529+
Deno.writeTextFileSync(quartoHtmlScript, renderedHtml);
530+
dest.push(quartoHtmlScript);
531+
}
526532
}
527533
}
528534

@@ -636,6 +642,7 @@ export async function htmlFormatExtras(
636642
const metadata: Metadata = {};
637643
return {
638644
[kIncludeInHeader]: includeInHeader,
645+
[kIncludeBeforeBody]: includeBeforeBody,
639646
[kIncludeAfterBody]: includeAfterBody,
640647
metadata,
641648
templateContext,

0 commit comments

Comments
 (0)