-
Notifications
You must be signed in to change notification settings - Fork 330
Comparing changes
Open a pull request
base repository: GoogleChromeLabs/ProjectVisBug
base: main
head repository: RoleModel/ProjectVisBug
compare: main
- 10 commits
- 65 files changed
- 3 contributors
Commits on Aug 27, 2026
-
route style edits through a store so they can be undone and exported
Every feature wrote `el.style[prop] = value` directly, which made two things impossible: recording a before/after for undo, and exporting usable CSS instead of a page full of inline styles. Introduce app/core as the single funnel. editStyle() writes the declaration into an editor-owned stylesheet keyed by a generated class and hands a change record to the history journal. Selectors repeat the class three times (0,3,0) so the rule beats most author CSS without resorting to !important, which would be noise in an export. history.js journals DOM moves, attributes and text alongside styles, so duplicate, delete, group/ungroup and keyboard nudges all undo. Rapid edits coalesce on an idle window, and beginGesture/endGesture collapses a continuous drag into one entry. Bound to cmd+z / cmd+shift+z. Overlays and drag ghosts keep their inline styles — isEditorChrome() keeps ephemeral UI out of the journal and out of exports. Export falls out cheaply now that edits live in a real stylesheet: /export, /export css strip the editor's bookkeeping and emit the markup alongside the rules. Existing tests asserted against el.style, so they read the authored value back through the new readStyle helper. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for f75e6f9 - Browse repository at this point
Copy the full SHA f75e6f9View commit details -
snap dragged elements into place using the drop container's layout
Dragging used to call swapElements(), which exchanged two siblings. It could not insert between them, could not cross into another container, refused to run when the element had no siblings, and never once looked at the parent's display — flex, grid and block all behaved identically. dropzones.js resolves a real insertion point from the container's layout: a caret along the main axis of a flex container (honouring row-reverse and grouping wrapped items into lines), a cell in a grid, a line-aware caret in inline flow, row/cell insertion in tables, and free XY placement with edge snapping for absolutely positioned elements. Empty containers now accept drops. It is pure geometry — move.js applies the result. For block and inline containers the axis is measured rather than read off `display`: a block container full of inline-block children lays out as a row, and trusting display alone drew the caret on the wrong axis. Grid distinguishes the two cases. An auto-flow grid reorders in the DOM and lets the browser re-place, preserving auto-placement; a grid whose children are explicitly placed pins the dragged element to the cell. move.js drives this with pointer events instead of HTML5 drag-and-drop, for precise coordinates and control over the overlay. A 4px threshold keeps a plain click selecting rather than dragging, and the whole gesture commits as one undo entry. Keyboard nudging is unchanged. visbug-insertion draws the caret and cell highlight. It needs `inset: … auto auto …` to escape the popover UA styles that would otherwise centre it in the viewport, matching the other overlays, and joins isOffBounds so it never becomes its own drop target. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 8ecf992 - Browse repository at this point
Copy the full SHA 8ecf992View commit details -
add an export button that saves the page as one HTML and one CSS file
Export existed only as a search command, and it emitted just the editor's own rules — the page's stylesheets stayed behind as <link> tags pointing at the origin, so a saved file looked unstyled offline. collectCSS() now gathers everything that styles the page: inline <style> blocks, same-origin links, @import-ed sheets, adopted stylesheets, and cross-origin sheets whose cssRules throw and have to be fetched instead. media="print" links are wrapped in @media so their scope survives, and url()s are rewritten against their own sheet's URL so images and fonts still resolve from the saved copy. The editor's rules go last so they win. The HTML gets the same treatment: src/href/srcset resolved to absolute, editor markup and bookkeeping attributes dropped. Scripts are stripped — an export is a snapshot of how the page looks now, and left in place the page's own scripts re-run on open and rebuild the DOM out from under it, VisBug's bundle included. The button sits in a new actions row under the colors. Saving two files makes Chrome ask once to allow multiple downloads; /export single still folds the CSS into a <style> tag for one self-contained file. Two fixes found while testing: the editor stylesheet was emitted twice, because the dedup compared pretty-printed text against cssText and never matched — it now skips by identity. And the toolbar, already taller than a 1366x768 viewport before this row, cut the new button off entirely, so it tightens up on short screens rather than putting items out of reach. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for d64efcd - Browse repository at this point
Copy the full SHA d64efcdView commit details -
replace the download button with one that copies the edits as a prompt
Downloading a flattened page is the wrong shape for getting design changes back into a codebase — nobody wants a 5000-line stylesheet, they want to know which elements changed and what happened to them. The hard part isn't listing the edits, it's naming the element each one belongs to in a way that survives the trip from a rendered page back to source. No single selector does that: an nth-child path is unique but says nothing about which component owns it, a class is meaningful but may repeat, a test id is decisive but often absent. So every element ships with each anchor we can establish — test attribute, id, css selector, opening tag, text, ancestor trail, dom path — ordered by how well they tend to map onto code, and the agent picks whichever fits the codebase in front of it. The css selector falls back to an id-scoped nth-child so it stays unique without losing the container's name. changes.js records only what a thing looked like *before* VisBug touched it. The net change is worked out at report time against what's authored now, so forty arrow-key nudges read as one change and anything undone drops out on its own — replaying the journal would have reported both. Anchors are cleaned through the DOM rather than by regex, so no data-vb-id, generated class, grab cursor or empty style attribute leaks into text that is meant to look like source. Downloading is still available as /export; the prompt is also on /copy changes. Capturing originals moved to edit.js, which breaks the import cycle that would otherwise exist between changes.js and style-store.js. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 194816a - Browse repository at this point
Copy the full SHA 194816aView commit details -
read the page's design tokens and use them when editing padding, marg…
…in, font, box-shadow, and color VisBug's nudges were pure px arithmetic, which fights a page built on a token scale. app/core/tokens.js discovers a page's own CSS custom properties (or Optics' specifically, via a cross-origin-safe probe), groups the ones that form a scale, and lets margin/padding/font/box-shadow step through them instead of by raw pixels — shift is the escape hatch back to px. Margin/padding measurement overlays now read as the token name (e.g. --op-space-medium) when a value lands exactly on a scale step. Color picking gets a matching swatch list drawn from the page's palette. Also fixes a race in extension/visbug.js where color-mode/scheme preferences could be sent before toolbar/inject.js had registered its listener on first launch, and extracts that send into extension/contextmenu/send.js so it's handled once instead of at each call site. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for a01156f - Browse repository at this point
Copy the full SHA a01156fView commit details -
Configuration menu - View commit details
-
Copy full SHA for 39efc5d - Browse repository at this point
Copy the full SHA 39efc5dView commit details -
group the copy-changes button with the color swatches
Moves the copy-prompt button into the same <ol colors> as the foreground/background/border swatches so it reads as one group, and swaps its bespoke circle styling for the shared color-swatch look.
Configuration menu - View commit details
-
Copy full SHA for a363929 - Browse repository at this point
Copy the full SHA a363929View commit details -
Configuration menu - View commit details
-
Copy full SHA for 6f73830 - Browse repository at this point
Copy the full SHA 6f73830View commit details -
Configuration menu - View commit details
-
Copy full SHA for 8d55725 - Browse repository at this point
Copy the full SHA 8d55725View commit details
Commits on Sep 8, 2026
-
Merge pull request #1 from RoleModel/christmas-bullet
Undoable, exportable edits with layout- and token-aware editing
Configuration menu - View commit details
-
Copy full SHA for bb011b8 - Browse repository at this point
Copy the full SHA bb011b8View commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff main...main