From a538651e3266a2d26d2f07dd5b18bd47b911f768 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Fri, 30 Aug 2024 15:41:27 +0200 Subject: [PATCH 1/4] theme - Refactor cleaning of sourceMappingURLs and apply it to revealjs too. --- src/command/render/pandoc-html.ts | 31 ++++++------------------ src/core/sass.ts | 14 +++++++++++ src/core/write.ts | 27 +++++++++++++++++++++ src/format/reveal/format-reveal-theme.ts | 3 +++ tests/docs/smoke-all/2024/05/03/9548.qmd | 6 +++-- 5 files changed, 55 insertions(+), 26 deletions(-) create mode 100644 src/core/write.ts diff --git a/src/command/render/pandoc-html.ts b/src/command/render/pandoc-html.ts index 2f21943d1a0..3d1f9683a3d 100644 --- a/src/command/render/pandoc-html.ts +++ b/src/command/render/pandoc-html.ts @@ -19,7 +19,7 @@ import { ProjectContext } from "../../project/types.ts"; import { TempContext } from "../../core/temp.ts"; import { cssImports, cssResources } from "../../core/css.ts"; -import { compileSass } from "../../core/sass.ts"; +import { cleanSourceMappingUrl, compileSass } from "../../core/sass.ts"; import { kSourceMappingRegexes } from "../../config/constants.ts"; @@ -38,6 +38,7 @@ import { kMinimal } from "../../format/html/format-html-shared.ts"; import { kSassBundles } from "../../config/types.ts"; import { md5HashBytes } from "../../core/hash.ts"; import { InternalError } from "../../core/lib/error.ts"; +import { writeTextFileSyncPreserveMode } from "../../core/write.ts"; // The output target for a sass bundle // (controls the overall style tag that is emitted) @@ -127,7 +128,8 @@ export async function resolveSassBundles( for (const target of targets) { let cssPath = await compileSass(target.bundles, temp); - + // First, Clean CSS + cleanSourceMappingUrl(cssPath); // look for a sentinel 'dark' value, extract variables const cssResult = processCssIntoExtras(cssPath, extras, temp); cssPath = cssResult.path; @@ -436,13 +438,8 @@ function processCssIntoExtras( temp: TempContext, ): CSSResult { extras.html = extras.html || {}; - const css = Deno.readTextFileSync(cssPath).replaceAll( - kSourceMappingRegexes[0], - "", - ).replaceAll( - kSourceMappingRegexes[1], - "", - ); + + const css = Deno.readTextFileSync(cssPath); // Extract dark sentinel value const hasDarkSentinel = cssHasDarkModeSentinel(css); @@ -474,21 +471,7 @@ function processCssIntoExtras( const hash = md5HashBytes(new TextEncoder().encode(cleanedCss)); const newCssPath = temp.createFile({ suffix: `-${hash}.css` }); - // Preserve the existing permissions if possible - // See https://github.com/quarto-dev/quarto-cli/issues/660 - let mode; - if (Deno.build.os !== "windows") { - const stat = Deno.statSync(cssPath); - if (stat.mode !== null) { - mode = stat.mode; - } - } - - if (mode !== undefined) { - Deno.writeTextFileSync(newCssPath, cleanedCss, { mode }); - } else { - Deno.writeTextFileSync(newCssPath, cleanedCss); - } + writeTextFileSyncPreserveMode(newCssPath, cleanedCss); return { dark: hasDarkSentinel, diff --git a/src/core/sass.ts b/src/core/sass.ts index d50f20f0d53..6196d47ac0d 100644 --- a/src/core/sass.ts +++ b/src/core/sass.ts @@ -17,6 +17,8 @@ import * as ld from "./lodash.ts"; import { lines } from "./text.ts"; import { sassCache } from "./sass/cache.ts"; import { md5HashBytes } from "./hash.ts"; +import { kSourceMappingRegexes } from "../config/constants.ts"; +import { writeTextFileSyncPreserveMode } from "./write.ts"; export interface SassVariable { name: string; @@ -327,3 +329,15 @@ export async function compileWithCache( return outputFilePath; } } + +// Clean sourceMappingUrl from css after saas compilation +export function cleanSourceMappingUrl(cssPath: string): void { + const cleaned = Deno.readTextFileSync(cssPath).replaceAll( + kSourceMappingRegexes[0], + "", + ).replaceAll( + kSourceMappingRegexes[1], + "", + ); + writeTextFileSyncPreserveMode(cssPath, cleaned); +} diff --git a/src/core/write.ts b/src/core/write.ts new file mode 100644 index 00000000000..64e128f590c --- /dev/null +++ b/src/core/write.ts @@ -0,0 +1,27 @@ +/* + * write.ts + * + * Copyright (C)2024 Posit Software, PBC + */ + +export function writeTextFileSyncPreserveMode( + path: string, + data: string, + options?: Deno.WriteFileOptions | undefined, +): void { + // Preserve the existing permissions if possible + // See https://github.com/quarto-dev/quarto-cli/issues/660 + let mode; + if (Deno.build.os !== "windows") { + const stat = Deno.statSync(path); + if (stat.mode !== null) { + mode = stat.mode; + } + } + + if (mode !== undefined) { + options = { ...options, mode }; // Merge provided options with mode + } + + Deno.writeTextFileSync(path, data, options); +} diff --git a/src/format/reveal/format-reveal-theme.ts b/src/format/reveal/format-reveal-theme.ts index 34de077e599..cef4f79a7af 100644 --- a/src/format/reveal/format-reveal-theme.ts +++ b/src/format/reveal/format-reveal-theme.ts @@ -20,6 +20,7 @@ import { isFileRef } from "../../core/http.ts"; import { pathWithForwardSlashes } from "../../core/path.ts"; import { formatResourcePath } from "../../core/resources.ts"; import { + cleanSourceMappingUrl, compileSass, mergeLayers, outputVariable, @@ -188,6 +189,8 @@ export async function revealTheme( // compile sass const css = await compileSass([bundleLayers, ...brandLayers], temp); + // Remove sourcemap information + cleanSourceMappingUrl(css); // convert from string to bytes const hash = md5HashBytes(Deno.readFileSync(css)); const fileName = `quarto-${hash}`; diff --git a/tests/docs/smoke-all/2024/05/03/9548.qmd b/tests/docs/smoke-all/2024/05/03/9548.qmd index bc44ec5db33..415527c6e05 100644 --- a/tests/docs/smoke-all/2024/05/03/9548.qmd +++ b/tests/docs/smoke-all/2024/05/03/9548.qmd @@ -6,12 +6,14 @@ _quarto: tests: revealjs: ensureHtmlElements: - - ['head > link[rel="stylesheet"][href$="quarto-4f64e0fc78c89fc90127583bb01c366c.css"]'] + - [] - ['head > link[rel="stylesheet"][href$="beige.css"]'] + ensureFileRegexMatches: + - ['.css` using SASS and the `theme: beige` should internally by overridden to `theme: quarto` so that the later is added in Pandoc's template +User provided them9548_files/libs/revealjs/dist/theme/e should be used to build a `quarto-.css` using SASS and the `theme: beige` should internally by overridden to `theme: quarto` so that the later is added in Pandoc's template 2024-08-26: `quarto.css` now carries the MD5 hash of the content to allow different revealjs themes to work on the same website. From 6ca4c9d8ebae3fd6b799915f95e96d47c0d7a03e Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Fri, 30 Aug 2024 17:10:06 +0200 Subject: [PATCH 2/4] revealjs - don't add empty css file as dependency This happens with `quarto-html` dependency, which can be emptied when it contains only the `quarto-variables-start` part. Detecting this helps reduce unneeded typescript processing, and inserting an empty file. --- src/command/render/pandoc-html.ts | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/command/render/pandoc-html.ts b/src/command/render/pandoc-html.ts index 3d1f9683a3d..20cac21e86b 100644 --- a/src/command/render/pandoc-html.ts +++ b/src/command/render/pandoc-html.ts @@ -127,12 +127,18 @@ export async function resolveSassBundles( } for (const target of targets) { - let cssPath = await compileSass(target.bundles, temp); + let cssPath: string | undefined; + cssPath = await compileSass(target.bundles, temp); // First, Clean CSS cleanSourceMappingUrl(cssPath); // look for a sentinel 'dark' value, extract variables const cssResult = processCssIntoExtras(cssPath, extras, temp); cssPath = cssResult.path; + + // it can happen that processing generate an empty css file (e.g quarto-html deps with Quarto CSS variables) + // in that case, no need to insert the cssPath in the dependency + if (!cssPath) continue; + // Process attributes (forward on to the target) for (const bundle of target.bundles) { if (bundle.attribs) { @@ -427,7 +433,7 @@ function generateThemeCssClasses( } interface CSSResult { - path: string; + path: string | undefined; dark: boolean; } @@ -468,10 +474,14 @@ function processCssIntoExtras( if (dirty) { const cleanedCss = css.replaceAll(kVariablesRegex, ""); - const hash = md5HashBytes(new TextEncoder().encode(cleanedCss)); - const newCssPath = temp.createFile({ suffix: `-${hash}.css` }); - - writeTextFileSyncPreserveMode(newCssPath, cleanedCss); + let newCssPath: string | undefined; + if (cleanedCss.trim() === "") { + newCssPath = undefined; + } else { + const hash = md5HashBytes(new TextEncoder().encode(cleanedCss)); + newCssPath = temp.createFile({ suffix: `-${hash}.css` }); + writeTextFileSyncPreserveMode(newCssPath, cleanedCss); + } return { dark: hasDarkSentinel, From 46746ee1126f2e1a241681429602a5759d8fdcff Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Fri, 30 Aug 2024 21:00:56 +0200 Subject: [PATCH 3/4] fix really wrong insertion --- tests/docs/smoke-all/2024/05/03/9548.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/docs/smoke-all/2024/05/03/9548.qmd b/tests/docs/smoke-all/2024/05/03/9548.qmd index 415527c6e05..80329e83709 100644 --- a/tests/docs/smoke-all/2024/05/03/9548.qmd +++ b/tests/docs/smoke-all/2024/05/03/9548.qmd @@ -14,6 +14,6 @@ _quarto: # Revealjs theme handling -User provided them9548_files/libs/revealjs/dist/theme/e should be used to build a `quarto-.css` using SASS and the `theme: beige` should internally by overridden to `theme: quarto` so that the later is added in Pandoc's template +User provided theme should be used to build a `quarto-.css` using SASS and the `theme: beige` should internally by overridden to `theme: quarto` so that the later is added in Pandoc's template 2024-08-26: `quarto.css` now carries the MD5 hash of the content to allow different revealjs themes to work on the same website. From 0e0d27f39f9fd83a3ee4621219e716cf2b6d0884 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 2 Sep 2024 16:20:02 +0200 Subject: [PATCH 4/4] Add entries in changelog --- news/changelog-1.6.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/news/changelog-1.6.md b/news/changelog-1.6.md index 3ed40d1e6c8..748574276dd 100644 --- a/news/changelog-1.6.md +++ b/news/changelog-1.6.md @@ -14,7 +14,9 @@ All changes included in 1.6: ## `revealjs` Format -- Update to Reveal JS 5.1.0 +- Update to Reveal JS 5.1.0. +- Prevent empty SASS built css file to be included in header. +- Remove wrong `sourceMappingUrl` entry in SASS built css. - ([#7715](https://github.com/quarto-dev/quarto-cli/issues/7715)): Revealjs don't support anymore special Pandoc syntax making BulletList in Blockquotes become incremental list. This was confusing and unexpected behavior. Supported syntax for incremental list is documented at . - ([#9742](https://github.com/quarto-dev/quarto-cli/issues/9742)): Links to cross-referenced images correctly works.