chore(deps): upgrade frappe-ui to 1.0.0-beta.55 - #752
Draft
NagariaHussain wants to merge 34 commits into
Draft
Conversation
Inventory of the 696-commit delta, restricted to what touches wiki: four loud breaks, thirteen silent ones, two non-idempotent codemods, and a phased order that puts the useFileUpload privacy audit first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Clears every break in the delta that fails the build. - tiptap moves to 3.29.2 as a set. @tiptap/markdown declares exact peers on @tiptap/core and @tiptap/pm at its own version, so a partial bump leaves two cores in the tree. yarn v1 ignores a "@tiptap/**" glob resolution, so all 43 packages are pinned explicitly. - frappe-ui/editor-style.css and frappe-ui/list-style.css are gone. The editor and list barrels self-import their CSS and are marked side-effectful, so the stylesheets ship with the subpath imports. The built output still carries 119 ProseMirror and 36 list-slot rules. - pageMetaPlugin is removed. Nothing declares the pageMeta() option; Spaces.vue already uses usePageMeta. - Alert is redesigned and stateless. It was registered globally with no call sites, so the registration goes rather than the migration. - Autocomplete is removed. AssignDialog used it with `multiple`, so it becomes MultiSelect, whose model is a value array rather than option objects. - tailwind.config.js spreads the preset's own `content` export. The hand-written globs it replaces covered src/components and src/molecules only, dropping every class the editor and list molecules emit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The named radius aliases are removed in frappe-ui 1.0.0 (ADR-0006). The preset replaces Tailwind's borderRadius scale, so an unmigrated rounded-md emits no CSS at all — square corners, no build error. Applied with `tokens-v2 --radius-only` across the editor SPA and the public reader's Jinja templates: 113 renames over 29 files. --radius-only rather than the full codemod because the color and typography passes already ran during the beta.25 upgrade and neither is idempotent. The three var(--radius-sm|lg) reads are hand-migrated — the codemod only rewrites rounded-* classes, and the alias CSS variables go away with the aliases. Pixel values are identical throughout; this changes vocabulary, not rendering. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The updated espresso v2 export shifts every chromatic ink scale down one level — the new ink-red-1 is the old ink-red-2 — and the scales now end at -9. ink-gray keeps its own 9-step scale and does not shift. Nothing warns: every ink-<family>-N site renders one shade off after the token update, so this lands with the upgrade rather than after it. Applied with `tokens-v2 --ink-shift` over frontend/src and wiki/templates (33 renames, 11 files). The mode has no sentinel it can read back from file content, so it writes a .tokens-v2-ink-shift marker in each target and refuses to run again; the markers are committed so a fresh clone keeps the guard. The six var(--ink-<family>-N) reads in the reader's hand-written CSS are migrated by hand — they sit beside generated files the codemod would rewrite for nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
None of these fail the build. Each one renders wrong instead. - Tabs is a composed family now and models the trigger value, not an index, so the index round-trip through the tab query goes away. Composed rather than the `:tabs` shorthand because v1 ships no layout defaults: the panel has to be a constrained flex column for ContributionsPanel to scroll, and generated panels take no classes. - Dropdown ignores `placement` and falls back to align="start", so both right-aligned menus quietly moved left. - PageHeaderMobile's #left/#right are #prefix/#suffix. Vue drops content passed to an unknown slot, so the tree toggle and the two menus just stopped rendering. - Combobox's template ref exposes clear(), not reset(). Audited and unchanged: all three useFileUpload calls already pass `private: false`, so the default flip to private cannot 403 an editor image or a space logo; Select's trigger slot is unused. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The change-card locator matched on `rounded-lg`, which the radius codemod renamed to `rounded-6` in the source. The class is gone from the markup, so the locator resolved to nothing and the Reordered label assertion timed out. The only e2e locator in the suite that matched on a token class. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Records the two corrections the work forced on the plan — the radius codemod needs --radius-only because the color and typography passes already ran and are not idempotent, and the tiptap resolutions have to name all 43 packages because yarn v1 ignores a glob — plus the four breaks that turned out to need no change, and the e2e baseline that separates the upgrade's one real test break from local flake. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
frappe-ui 1.0.0-beta.41 switched sync-tokens to oklch, so colors.json
holds oklch() where it used to hold hex. The OG card template declares
those six values inline, and the drift test compares the two directly:
AssertionError: '#0f0f0f' != 'oklch(0.168 0 0)'
The card renders through headless Chromium, which reads oklch, so the
template carries the new notation rather than a hex approximation of it.
The test's scraper accepts either notation, so it keeps comparing what
colors.json actually holds instead of assuming one form.
TEMPLATE_VERSION is part of the cache fingerprint, so bumping it drops
every cached card.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A callout's markdown never reached a fixed point under tiptap 3.29.2:
every parse/serialize pass appended two more newlines, so repeated saves
inflated the stored content without bound.
:::note[Test]\nhello\n:::\n\n\n\n
:::note[Test]\nhello\n:::\n\n\n\n\n\n
:::note[Test]\nhello\n:::\n\n\n\n\n\n\n\n
renderMarkdown appended its own `\n\n` after the closing fence. The
serializer already separates blocks and the doc's trailing empty
paragraph serialises to another blank line, which put four newlines after
the fence. Four is one past where PreserveBlankLines turns marked's
`space` token into a real empty paragraph, and that paragraph then
serialised to two more newlines on the next pass. Paragraphs, headings
and lists were stable throughout because they leave the separator to the
serializer; the callout is now the same.
The markdown hooks move to callout-markdown.js so they can be tested:
callout-block.js imports a .vue node view at the top level, which
`node --test` cannot load. Verified by reverting the one-line change with
the tests in place — six round-trip cases and both direct assertions fail
without it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
FeatherIcon and its bare-name back-compat are removed in frappe-ui 1.0.0 (ADR-0008). A string that does not start with `lucide-` now resolves to nothing — renderIcon returns null and dev logs one warning per component and prop — so every `icon="settings"` and `icon: 'trash-2'` in the app silently stopped drawing: dropdown rows, tree actions, review actions, the space chrome bar. All 41 sites take the `lucide-` prefix. Every name survives the move except `github`, which lucide dropped along with the rest of its brand icons; the two GitHub affordances use `lucide-git-branch`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
SidebarHeader is a fixed 48px region that owns its own gutter, so it is meant to go straight into Sidebar. Our wrapping `p-2` div added a second one, pushing the logo and title in past every row below them. Padding moves to the scroll region and the footer, which is what v1's composition contract asks for now that Sidebar no longer applies any of its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
useColorScheme owns everything the local composable was doing by hand: the `data-theme` attribute, persistence, following the OS, and muting transitions across a swap so the page doesn't flash. Its version also cancels a pending unmute, so back-to-back swaps can't uncover a repaint — which the two-rAF dance here could. The `.no-transition` rule goes too; frappe-ui/style.css ships it. What stays local, and why: - The toggle flips the *painted* scheme rather than delegating to toggleColorScheme, which branches on the preference: starting from `system` on a dark OS it picks `dark`, and the first click looks dead. - `resolvedTheme` tracks the `data-theme` attribute through a MutationObserver. DiffViewer and MermaidBlockView need the painted scheme, and it isn't derivable from the preference — `system` resolves against the OS, and an OS flip repaints without changing the preference, so there is nothing reactive to watch. The storage key moves from `wiki-theme` to frappe-ui's `theme`. A saved value under the old key is copied over once, and the public reader — which keeps its own Alpine implementation, having no frappe-ui to import — reads the new key with the old one as a fallback and writes the new one, so a toggle on either surface still reaches the other. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
All three tab panels rendered at once, splitting the height three ways and clipping the list after about three rows. reka keeps an inactive TabsContent's wrapper in the DOM and drops only its slot content, marking the wrapper with `hidden`. Tailwind's preflight turns that into `display: none` via `[hidden]`, which is a single attribute selector — exactly as specific as a `.flex` utility, and utilities are emitted after preflight. So the `flex` this call site put on TabPanel won the cascade, and every panel stayed a visible flex child claiming `flex-1`. Moving `display` behind `data-[state=active]:` leaves `hidden` to win on the inactive ones. `min-h-0` and `flex-1` are inert while hidden, so they can stay unconditional. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The underline variant's indicator is a 1px rail line. It measured and positioned correctly, but against the dark theme it reads as part of the track border rather than as a selection, so the active tab looked unmarked. TabList has full variant parity with TabButtons, so the button-style track is a prop rather than a different component — and the composed family keeps owning the panels, which TabButtons does not do. Page padding moves to a wrapper: the pill track hugs its content, so padding on TabList itself would sit inside the pill. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`icon: node.is_published ? 'eye-off' : 'eye'` kept bare Feather names, so the publish toggle in the tree's three-dot menu drew no icon. The upgrade sweep that prefixed the other 41 call sites matched `icon: '...'` and `icon="..."` only — a ternary's branches were invisible to it, and it ran over .vue files alone. Rather than grep harder next time, this adds a test that walks every source file, isolates each icon key or prop's own expression, and fails on any string literal in it that is not a `lucide-` class. It reads ternaries, template props and bindings, and .js as well as .vue. The break is silent by design — v1 renders null for an unsupported icon string and only warns in dev — so a build and a passing e2e run both stay green while the icon is missing. Verified by restoring the bare names with the test in place. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two breaking changes land in the wiki: - Badge dropped the `orange` theme. Every `orange` badge — unpublished pages, dirty settings panels, reordered nodes, "In Review" change requests — moves to `amber`, the nearest surviving warm theme. An unrecognised theme renders no color classes at all, so these badges would otherwise have gone unstyled. - SettingsDialog renamed its open model from `modelValue` to `open`. Both wrappers now bind `v-model:open`. Dialog's `yellow` theme also became `amber`, and the v1 chart family, CommandPalette and `useShortcut` left the root export for `frappe-ui/experimental` — none of which this app uses. Verified in the browser: both settings dialogs open, close on Escape and reopen; badges render in light and dark. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The light-mode content pane floated as a rounded, shadowed card over the sidebar surface while dark mode was already flat. The app window rounds the outer corners itself, so the inner radius only read as noise — both themes now share one flush treatment with a hairline divider. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Both tables already used the frappe-ui/list family but diverged from the documented idioms in three ways. Skeletons and rows now share one List, so the track list is declared once instead of being mirrored in a hand-built grid that could drift from it. `list-row-px-3` sets the content inset on the List, which flows to both the header and the rows; without it the header sat flush while the interactive rows carried the family's default 0.75rem. Mobile collapses each table to a feed through a `--list-columns` override rather than scrolling a min-width table sideways. The header needs `!hidden` there: the family sets `display: grid` at attribute specificity to survive preflight resets, which a plain `hidden` utility ties with and loses to on order. Also drops the `selectable` / `showTooltip` / `resizeColumn` options left over from the config-driven ListView — nothing reads them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The space list was a four-column table (name, status, route, a View button) that needed a responsive override to survive a phone. The list family's default feed template carries the same information in less space and reflows on its own, so the override is gone. Each row is now a square Avatar of the space logo, the space name over its route, and the page count above the published badge. Page counts come from a new grouped query rather than a field on the list: Wiki Space stores no count, and a call per row would scale with the page size. Groups are folders and external links point elsewhere, so neither counts as a page; unpublished pages do, since this is the editor's list and a draft is still a page to maintain. The View button is dropped — the row already opens the space, and the public reader is one click away from there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…list The list ran the full width of the content pane, which left every trailing cell a screen away from the title it belonged to. It now reads as a centered column, with search, the filter, and the tally sharing one row above it. Search comes first, then a TabButtons segmented control for All / Published / Unpublished, then the number of spaces on the far side. The row wraps on mobile so search keeps a line to itself. Status moves out of the trailing cell into a column of its own, so the badges line up down the list instead of stacking under the page counts. The page-count column is the one dropped on mobile. get_space_count backs the tally. It takes the same search and filter the list does, because frappe.client.get_count has no or-filters and the list searches name *or* route -- counting through it would have tallied something other than what is on screen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The list scrolled in a plain overflow-auto div inside the narrow column, so the scrollbar ran down the middle of the pane beside the rows. frappe-ui's ScrollArea now owns the scroll region and spans the pane, so its overlay scrollbar rides the content edge. The narrow width moves onto the toolbar and the row wrapper, which repeat it so the two still line up; the page box drops its padding, since the scroll region has to reach the edge and the horizontal inset belongs to the content inside it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Callouts are atom nodes whose body is a string attribute, so rich text needs a nested Editor and a hand-built B/I/Link toolbar. TipTap's container pattern (content expression + NodeViewContent) puts the body in the main document instead, which brings every mark and block node the editor already has. Restyle to match frappe-ui's Alert at the same time: one neutral surface, color only in the icon. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The branch picker only offered what GitHub listed, so a branch outside the first page (or one the picker never loaded) could not be chosen at all. Autocomplete gains an `allow-custom` mode: typed text that matches no option is committed on Enter, blur, or outside-click, so clicking straight through to a dialog action still keeps the value. Esc still discards. `branch_exists` asks GitHub for the single branch rather than scanning `repo_branches`, which caps at 100, and the create form calls it before inserting so a typo surfaces in the dialog instead of failing the first sync. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The toolbar sat flush to the narrow column while the rows carried the List's own content inset, so the tally hung a row-inset past the status badges and search started a row-inset left of the avatars. Both now share one wrapper shape and the toolbar mirrors the row inset, so the two edges line up. Two columns join them. Last updated is the newest page edit in the space, not the space document's own `modified` -- that one moves when someone renames the space or flips a setting, which says nothing about whether the content is current, so a space with no pages shows nothing rather than a fresh-looking date. Open change requests counts anything not merged, rejected or archived, the same reading as an open pull request, and takes the pull-request glyph. Both are an icon and a number rather than a phrase: at this column width the glyph carries the label and the title attribute spells it out. The three measure columns drop on mobile, where the status badge is the one thing worth the width. get_space_page_counts becomes get_space_stats and returns all three in one call, so the row still costs a single round trip. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The body was a markdown string in an attribute, so the node view ran a second Editor and a hand-built B/I/Link toolbar to make three marks editable. It is now real document content (content: 'block+' plus NodeViewContent), which hands the callout every mark and block node the main editor already has: lists, headings, code blocks, images, Cmd+K links, the bubble menu and undo history. The stored format is unchanged, so no migration: the fence body is tokenized with the lexer and parsed into child nodes, and serialized back through renderChildren. The markdown unit tests grow the block-children cases and a fidelity check — a fixed point alone proves nothing, since content that degrades to plain text round-trips just as stably. Registering the plain CodeBlock in the harness is what makes the fenced-block case meaningful: wikiStarterKit disables it because frappe-ui's version can't load under node --test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The row had grown to six columns of icon-and-number pairs, which is not what the list family's feed recipe does. It is back to the recipe's shape: leading avatar, the two-line title block, and a right-aligned trailing stack of muted lines -- with the status badge lifted out into a column of its own between them. The trailing stack carries the page count over the last edit. Both read as prose again: "No pages" rather than "0 pages", and "Updated 9 minutes ago" rather than a bare "9 minutes ago", which read as an unlabelled timestamp for the whole row. The title column is capped rather than flexible, with the slack going to the trailing stack instead. On a 1fr title column a short space name left the status badge floating a third of the row away from the text it describes. Open change requests come back out. They were an extra grouped query for something the Change Requests page already presents properly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The title moves out of the dialog into an input in the header row, with the type's default title as its placeholder. Enter moves into the body. A callout is isolating, so ProseMirror's own exits don't apply: at the end of the document there is nothing after the node to move into. Mod-Enter and ArrowDown-at-the-end now open a paragraph after it, and Backspace at the start of an empty callout deletes the node instead of doing nothing. The e2e spec now creates a throwaway space per test rather than authoring into whichever space the site lists first. That space's page tree grows with every run and was never cleaned up, which is what made the suite flake locally once it held enough pages. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
frappe-ui ships raw source and reaches its own files through the `#molecules/*` imports map. esbuild resolves a mapped path with Node semantics and never tries an extension, so pre-bundling `frappe-ui/editor` and `frappe-ui/list` failed on every internal import — 57 "Could not resolve" errors and a dev server that served nothing. Vite's own resolver handles the same paths, so exclude the entries and let it serve them. Drop `feather-icons` and `interactjs` from optimizeDeps.include while here: neither package is installed or imported, and each logged a "Failed to resolve dependency" line on every dev start. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
One neutral surface (surface-gray-1, rounded-6, p-3, no border) with the type's colour carried only by the icon, which is now the same solid Figma status glyph Alert resolves for that theme. Those four SFCs are not exported from frappe-ui/icons, so the paths are inlined — the server-rendered reader needs the same ones in markdown.py anyway. Body typography follows Alert's description: full width under the header rather than indented beside it, since the header is its own row now. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The server-rendered callout gets the same treatment as the editor: a header row (icon + title) over a full-width body, one neutral surface, and the Alert status glyph in the type's colour. The `.callout-body` wrapper and the two-column grid are gone — the body is no longer indented beside the title. Public icons were also a shade off: they used the -2 inks where the SPA used -5. Print resolves the tokens to hex and floats the icon, since that pipeline has no CSS variables and QtWebKit parses neither oklch() nor flexbox. Drops the callout rules from wiki-rendered.css, whose only consumer — the standalone CR preview page — was removed in afb6808. The rest of that file is dead for the same reason but is left alone here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The default title was an input placeholder inked like real text, so it looked editable but wasn't: putting a cursor in it and pressing Backspace did nothing. It is a value now — seeded on insert, and filled in on parse for a fence written without [Title]. The serializer drops the brackets again while the title still equals the type's default, so a wiki full of :::note isn't rewritten to :::note[Note] the first time each page is saved. Clearing the title restores the default on blur, since the rendered page always prints one, and changing type only carries the title along if the author never touched it. The three-dot action is "Remove" rather than "Delete". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Alert's description is full-bleed, but every Alert story renders the component inside max-w-sm — a 384px status box with a one-sentence description. A callout is the document's width and holds paragraphs and lists, and at that size the title (indented behind the icon) and the body (at the container edge) give the block two left edges, so the header reads as detached from what it labels. The body is now indented to the title's left edge — the icon plus the header gap — in the editor, on the public page and in print. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #747, which stopped at
beta.45. Same branch point, more on top.Why?
We were on
frappe-ui@1.0.0-beta.25(20 July) and the delta only grew. Thistakes us to
1.0.0-beta.55in two hops, and carries the UI work that the newcomponent APIs made possible.
What?
The upgrade (
beta.25→beta.45→beta.55), with tiptap moved to3.29.2as a set. Breaking changes that reached us:frappe-ui/editor-style.cssandfrappe-ui/list-style.cssexports removed — the barrels self-import their CSS nowAutocompleteremoved →MultiSelectinAssignDialogpageMetaPluginremovedrounded-mdemits no CSS at all — 113 renames over 29 filesink-graydoes not shift — 33 renames over 11 filesTabsis a composed family and models the trigger value, not an indexDropdownignoresplacement; menus quietly left-alignPageHeaderMobile#left/#right→#prefix/#suffix— Vue drops unknown slots without a wordComboboxtemplate ref exposesclear(), notreset()Badgedropped theorangetheme →amber. An unrecognised theme renders no color classes at allSettingsDialogrenamed its open model frommodelValuetoopenCallouts become a container node. The body was a markdown string in an
attribute, so the node view ran a second Editor and a hand-built B/I/Link
toolbar for three marks. It is now real document content, which hands the
callout every mark and block the main editor has: lists, headings, code
blocks, images, Cmd+K links, the bubble menu, undo history. The stored format
is unchanged, so no migration. The title is edited in place in the header row,
and Mod-Enter / ArrowDown / Backspace give an isolating node real exits.
Styling matches frappe-ui's
Alertin the editor, on the public page, and inprint.
The space list becomes a feed. A four-column table that needed a
responsive override is now the list family's default feed row: avatar, name
over route, page count, status. Search, an All/Published/Unpublished filter
and a result tally share one row above a centered column. Two measure columns
join it — last updated (newest page edit, not the space's own
modified) andopen change requests.
Git sync accepts an arbitrary branch name. The picker only offered what
GitHub listed, so a branch past the first page could not be chosen.
Autocompletegains anallow-custommode, andbranch_existsasks GitHubfor the single branch instead of scanning the 100-capped
repo_branches, so atypo surfaces in the create dialog instead of failing the first sync.
Plus: theme swapping handed to frappe-ui (flash-free), the rounded card around
the content column dropped, and the list components moved onto the documented
frappe-ui/listrecipe.How?
Two codemod passes, both non-idempotent, landed with the version bump because
either half alone renders wrong:
tokens-v2 --radius-only— not the plain codemod, whose color andtypography passes already ran during the beta.25 upgrade
tokens-v2 --ink-shift, with its.tokens-v2-ink-shiftmarkers committed soa fresh clone keeps the re-run guard
The six
var(--ink-*)and threevar(--radius-*)reads in hand-written CSSare migrated by hand — the codemods only rewrite classes.
All 43 tiptap packages are pinned by name in
resolutions. Bumping only ourten direct deps left frappe-ui's transitive
@tiptap/extension-*at3.27.1,each declaring an exact
@tiptap/corepeer, which produced 19 nested copies ofcore; yarn v1 ignores a
"@tiptap/**"glob resolution.tailwind.config.jsnow spreads the preset's owncontentexport. Thehand-written globs it replaces covered
src/componentsandsrc/moleculesonly, silently dropping every class the editor and list molecules emit.
Testing
node --testoversrc/**/*.test.js), up from 47— the callout markdown suite gains block-children cases and a fidelity check.
A fixed point alone proves nothing: content that degrades to plain text
round-trips just as stably.
yarn buildclean. Verified the editor and list stylesheets still ship afterdropping the explicit CSS imports.
branch_existsand the space-list counts.authoring into whichever space the site lists first — that tree grew with
every run and was never cleaned up, which is what made it flake locally.
holds 1847 spaces and 11k documents of fixture data and the web server dies
partway through long runs. CI is the verdict.
Specs:
specs/frappe_ui_beta45_upgrade.md,specs/callout_container_node.md.🤖 Generated with Claude Code
https://claude.ai/code/session_01Pba2JytJJxKYqHw239BZY5