the gutter shows as you choose it, and the tab is in the URL
CHANGES APPEAR IMMEDIATELY. Colours and typefaces go into the frame as CSS custom properties because that is what the page reads them as. A gutter cannot: only a class can carry a breakpoint, and there is no variable to set instead. So the classes are swapped on the three elements marked `data-gutter`. That works for one reason worth stating — the classes are in the SITE's stylesheet, which the frame already has, and the site safelists every step. A class invented in the admin would silently do nothing, which is the failure this whole arrangement keeps circling. Only gutter classes are touched. Those three elements carry the gutter and nothing that looks like it — a section's own padding lands on the <section> and the band padding on <header> — so stripping `px-N` from them is safe where doing it to an arbitrary element would not be. Driven by the dependency list rather than a second code path: `gutter` is a dependency of onDocument, so changing it hands SitePreview a new function, whose effect runs the previous application's cleanup — putting the original classes back — and then applies the new ones. THE TAB IS IN THE URL. `?tab=padding`, same rule as the mode and the device: it is addressable. "Look at the typefaces" is a link somebody sends, and a reload that drops you back on Colours loses the place you were working in. Absent means Colours. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -442,3 +442,40 @@ export function paintMeasure(document: Document): () => void {
|
||||
for (const guide of guides) guide.remove();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The site's gutter, applied to a rendered page before it is saved.
|
||||
*
|
||||
* ── Why this can be classes and not variables ──
|
||||
*
|
||||
* Colours and typefaces go into the frame as CSS custom properties, because that is what the page reads
|
||||
* them as. A gutter is Tailwind classes — `px-4 md:px-8` — because only a class can carry a breakpoint,
|
||||
* and there is no variable to set instead.
|
||||
*
|
||||
* That works here for one reason: the classes are in the SITE's stylesheet, which the frame already
|
||||
* has. The site safelists every step (`@source inline` in styles.css), so any value this writes is one
|
||||
* the frame can already render. A class invented here would silently do nothing.
|
||||
*
|
||||
* ── Only gutter classes are touched ──
|
||||
*
|
||||
* The elements carrying `data-gutter` hold the gutter and nothing else that looks like it: a section's
|
||||
* own padding lands on the <section>, and the band padding on <header>. So removing everything matching
|
||||
* `px-N` from these three is safe, where doing it to an arbitrary element would not be.
|
||||
*/
|
||||
export function applyGutter(document: Document, classes: string): () => void {
|
||||
const targets = [...document.querySelectorAll<HTMLElement>('[data-gutter]')];
|
||||
const before = targets.map((element) => element.className);
|
||||
|
||||
const GUTTER = /^(?:md:|lg:)?px-\d+$/;
|
||||
|
||||
for (const element of targets) {
|
||||
const kept = element.className.split(/\s+/).filter((name) => name && !GUTTER.test(name));
|
||||
element.className = [...kept, ...classes.split(/\s+/).filter(Boolean)].join(' ');
|
||||
}
|
||||
|
||||
return () => {
|
||||
targets.forEach((element, index) => {
|
||||
element.className = before[index]!;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user