Skip to content

Commit 5b1af3f

Browse files
committed
scss analyzer - improve origin reporting and display
1 parent b08f5dd commit 5b1af3f

File tree

5 files changed

+48
-15
lines changed

5 files changed

+48
-15
lines changed

src/core/sass.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { cssVarsBlock } from "./sass/add-css-vars.ts";
2020
import { md5HashBytes } from "./hash.ts";
2121
import { kSourceMappingRegexes } from "../config/constants.ts";
2222
import { writeTextFileSyncPreserveMode } from "./write.ts";
23+
import { quartoConfig } from "../core/quarto.ts";
2324

2425
export interface SassVariable {
2526
name: string;
@@ -107,6 +108,7 @@ export async function compileSass(
107108
// * Rules may use functions, variables, and mixins
108109
// (theme follows framework so it can override the framework rules)
109110
let scssInput = [
111+
`// quarto-scss-analysis-annotation { "quarto-version": "${quartoConfig.version()}" }`,
110112
'// quarto-scss-analysis-annotation { "origin": "\'use\' section from format" }',
111113
...frameWorkUses,
112114
'// quarto-scss-analysis-annotation { "origin": "\'use\' section from Quarto" }',
@@ -119,11 +121,11 @@ export async function compileSass(
119121
...quartoFunctions,
120122
'// quarto-scss-analysis-annotation { "origin": "\'functions\' section from user-defined SCSS" }',
121123
...userFunctions,
122-
'// quarto-scss-analysis-annotation { "origin": "user-defined defaults" }',
124+
'// quarto-scss-analysis-annotation { "origin": "Defaults from user-defined SCSS" }',
123125
...userDefaults.reverse(),
124-
'// quarto-scss-analysis-annotation { "origin": "quarto-specific defaults" }',
126+
'// quarto-scss-analysis-annotation { "origin": "Defaults from Quarto\'s SCSS" }',
125127
...quartoDefaults.reverse(),
126-
'// quarto-scss-analysis-annotation { "origin": "format framework defaults" }',
128+
'// quarto-scss-analysis-annotation { "origin": "Defaults from the format SCSS" }',
127129
...frameworkDefaults.reverse(),
128130
'// quarto-scss-analysis-annotation { "origin": "\'mixins\' section from format" }',
129131
...frameworkMixins,

src/core/sass/analyzer/forward-annotations.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { annotateNode } from './ast-utils.ts';
1+
import { annotateNode } from "./ast-utils.ts";
22

33
export const forwardAnnotations = (ast: any) => {
44
const pragmaAnnotation = "quarto-scss-analysis-annotation";
5-
const currentAnnotation: Record<string, unknown> = {};
6-
let hasAnnotations: boolean = false
5+
const annotationStack: Record<string, string>[] = [{}];
6+
let currentAnnotation: Record<string, unknown> = annotationStack[0];
7+
let hasAnnotations: boolean = false;
78
for (const node of ast.children) {
89
if (node.type === "comment_singleline") {
910
const value = node?.value?.trim();
@@ -15,7 +16,18 @@ export const forwardAnnotations = (ast: any) => {
1516
console.error("Could not parse annotation payload", e);
1617
continue;
1718
}
19+
if (payload.action === "push") {
20+
annotationStack.push(JSON.parse(JSON.stringify(currentAnnotation)));
21+
currentAnnotation = annotationStack[annotationStack.length - 1];
22+
} else if (payload.action === "pop" && annotationStack.length) {
23+
annotationStack.pop();
24+
currentAnnotation = annotationStack[annotationStack.length - 1];
25+
}
26+
1827
for (const [key, value] of Object.entries(payload)) {
28+
if (key === "action") {
29+
continue;
30+
}
1931
if (value === null) {
2032
delete currentAnnotation[key];
2133
} else {
@@ -30,4 +42,4 @@ export const forwardAnnotations = (ast: any) => {
3042
}
3143
}
3244
return ast;
33-
}
45+
};

src/core/sass/brand.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,10 @@ const brandColorBundle = (
180180
key: string,
181181
nameMap: Record<string, string>,
182182
): SassBundleLayers => {
183-
const colorVariables: string[] = ["/* color variables from _brand.yml */"];
183+
const colorVariables: string[] = [
184+
"/* color variables from _brand.yml */",
185+
'// quarto-scss-analysis-annotation { "action": "push", "origin": "_brand.yml color" }',
186+
];
184187
for (const colorKey of Object.keys(brand.data?.color?.palette ?? {})) {
185188
colorVariables.push(
186189
`$${colorKey}: ${brand.getColor(colorKey)} !default;`,
@@ -204,6 +207,7 @@ const brandColorBundle = (
204207
}
205208
}
206209
// const colorEntries = Object.keys(brand.color);
210+
colorVariables.push('// quarto-scss-analysis-annotation { "action": "pop" }');
207211
const colorBundle: SassBundleLayers = {
208212
key,
209213
// dependency: "bootstrap",
@@ -224,6 +228,7 @@ const brandTypographyBundle = (
224228
): SassBundleLayers => {
225229
const typographyVariables: string[] = [
226230
"/* typography variables from _brand.yml */",
231+
'// quarto-scss-analysis-annotation { "action": "push", "origin": "_brand.yml typography" }',
227232
];
228233
const typographyImports: string[] = [];
229234
const fonts = brand.data?.typography?.fonts ?? [];
@@ -422,6 +427,9 @@ const brandTypographyBundle = (
422427
}
423428
}
424429

430+
typographyVariables.push(
431+
'// quarto-scss-analysis-annotation { "action": "pop" }',
432+
);
425433
const typographyBundle: SassBundleLayers = {
426434
key,
427435
// dependency: "bootstrap",

tools/sass-variable-explainer/forward-annotations.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { annotateNode } from './ast-utils.ts';
22

33
export const forwardAnnotations = (ast: any) => {
44
const pragmaAnnotation = "quarto-scss-analysis-annotation";
5-
const currentAnnotation: Record<string, unknown> = {};
6-
let hasAnnotations: boolean = false
5+
const annotationStack: Record<string, string>[] = [{}];
6+
let currentAnnotation: Record<string, unknown> = annotationStack[0];
7+
let hasAnnotations: boolean = false;
78
for (const node of ast.children) {
89
if (node.type === "comment_singleline") {
910
const value = node?.value?.trim();
@@ -15,7 +16,17 @@ export const forwardAnnotations = (ast: any) => {
1516
console.error("Could not parse annotation payload", e);
1617
continue;
1718
}
19+
if (payload.action === "push") {
20+
annotationStack.push(JSON.parse(JSON.stringify(currentAnnotation)));
21+
currentAnnotation = annotationStack[annotationStack.length - 1];
22+
} else if (payload.action === "pop" && annotationStack.length) {
23+
annotationStack.pop();
24+
currentAnnotation = annotationStack[annotationStack.length - 1];
25+
}
1826
for (const [key, value] of Object.entries(payload)) {
27+
if (key === "action") {
28+
continue;
29+
}
1930
if (value === null) {
2031
delete currentAnnotation[key];
2132
} else {

tools/sass-variable-explainer/sass-ui.qmd

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,13 @@ selectedDependencyTitle = {
105105
if (selectedDependency === undefined) {
106106
return htl.html`<h5>Select a single variable to analyze</h5>`;
107107
} else {
108-
return htl.html`<h5>Variable analysis for ${selectedDependency?.node?.property?.variable?.value ?? "<i>unknown</i>"}</h5>`;
108+
return htl.html`<h5>Variable analysis for <code>${selectedDependency?.node?.property?.variable?.value ?? "<i>unknown</i>"}</code></h5>`;
109109
}
110110
}
111111
renderedAnalysis = {
112112
deps;
113113
debugger;
114-
const result = htl.html`<div style="padding-left: 20px"></div>`;
114+
const result = htl.html`<div style="padding-left: 20px; padding-top: 20px"></div>`;
115115
if (!selectedDependencyChains.length) {
116116
return result;
117117
}
@@ -124,7 +124,7 @@ renderedAnalysis = {
124124
}
125125
126126
if (selectedDependency?.node?.annotation?.origin) {
127-
result.appendChild(htl.html`<div><b>Origin</b>: ${selectedDependency?.node?.annotation?.origin}</div>`);
127+
result.appendChild(htl.html`<div style="padding-bottom:1em"><b>Origin</b>: ${selectedDependency?.node?.annotation?.origin}</div>`);
128128
}
129129
130130
const lineEnd = Math.max(
@@ -133,14 +133,14 @@ renderedAnalysis = {
133133
selectedDependency?.node?.value?.lineEnd ?? -Infinity,
134134
);
135135
if (selectedDependency?.node?.line !== undefined && lineEnd !== -Infinity) {
136-
result.appendChild(htl.html`<div><b>SCSS source<b></div>`);
136+
result.appendChild(htl.html`<div><b>SCSS source:<b></div>`);
137137
const snippet = sourceLines.slice(selectedDependency?.node?.line - 1, lineEnd).join("\n");
138138
result.appendChild(htl.html`<div><pre style='padding-left: 20px; padding-top:1em'>${snippet}</pre></div>`)
139139
}
140140
141141
142142
// Dependencies
143-
result.appendChild(htl.html`<div>Dependencies:</div>`);
143+
result.appendChild(htl.html`<div><b>Dependencies:</b></div>`);
144144
const depsDiv = htl.html`<div style="padding-left: 20px"></div>`;
145145
result.appendChild(depsDiv);
146146
const seenDependencies = new Set([]);

0 commit comments

Comments
 (0)