feat: swizzable MarkdownActionsDropdown component#10
Open
guicara wants to merge 1 commit into
Open
Conversation
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.
Hi @FlyNumber,
Thank you for this great plugin!
Please find this PR to improve it by adding more customization options.
Summary
Refactor the plugin so consumers can swizzle
MarkdownActionsDropdowndirectly, instead of having to ejectRoot, and make the swizzled component self-contained so it builds correctly inside consumer Docusaurus sites.This improves the plugin's customization story while preserving the existing runtime behavior.
In my specific use case, I’m working with a Design System that already provides a dropdown component. Relying solely on CSS to customize it was not sufficient, so I swizzled the component and replaced the original JSX with the one from our Design System. I also added i18n support to handle multiple languages.
Problem
The plugin currently exposes
theme/Root.jsas the effective theme entry point and injects the dropdown from there. In practice, this creates two problems:The wrong swizzle target is exposed
Rootis not the real customization surface.The first refactor still had a portability issue
theme/MarkdownActionsDropdown, the component still imported:../../lib/markdown-pathno longer exists, so the consumer build fails.Goals
MarkdownActionsDropdownthe correct, first-class swizzle targetRootsrc/theme/What changed
1. Exposed
MarkdownActionsDropdownas a theme componentAdded a new canonical theme component:
This makes the dropdown discoverable by Docusaurus' theme/swizzle system.
2. Updated
Rootto use@theme/MarkdownActionsDropdownChanged
theme/Root.jsso it renders the dropdown through the theme alias:instead of importing it from a plugin-local path.
This is the key change that allows consumer overrides to work automatically.
3. Kept backward compatibility for the old component path
The old file:
was preserved as a compatibility re-export to the new theme component.
That avoids breaking any internal or consumer code that may have been importing from the old location.
4. Made the swizzled dropdown self-contained
The swizzlable component no longer imports plugin-local utility code like:
Instead, the tiny
getMarkdownUrl()helper is defined locally insidetheme/MarkdownActionsDropdown/index.js.This ensures that when Docusaurus ejects the component into a consumer project, the copied file still builds correctly on its own.
5. Updated documentation
Updated
README.mdto:MarkdownActionsDropdownas the supported swizzle targetRootswizzle guidanceExample new workflow:
Why this approach
Why keep
Rootat all?Rootstill serves an important purpose:That behavior is internal plugin infrastructure, not the ideal consumer customization surface.
So the design keeps:
Rootfor injection/orchestrationMarkdownActionsDropdownfor user customizationThis separation is a better fit for how Docusaurus theme APIs are intended to be used.
Why use
@theme/MarkdownActionsDropdown?Because
@theme/...is the extension point Docusaurus resolves through its theme override system.Using
@theme/MarkdownActionsDropdownmeans:Why inline the helper instead of importing from
lib/?Swizzled theme components are physically copied into the consumer site.
That means relative imports to plugin internals are fragile unless those internals are also exposed as stable public modules. In this case,
getMarkdownUrl()is tiny and stable, so inlining it is the simplest and most reliable solution.Benefits:
Trade-off:
This trade-off is worth it here because portability of the swizzled file is more important than centralizing a 3-line helper.
User-facing result
After this change, consumers can now do:
and Docusaurus will generate:
They can then customize the dropdown directly without needing to eject
Root.Also, the swizzled file now builds correctly because it no longer depends on plugin-internal relative imports.
Backward compatibility
This change is intended to be backward compatible:
Rootcontinues to manage injection as beforeThe only behavior change is improved customization support.
Testing / Validation
Plugin test suite
Ran:
npm testResult:
Package validation
Ran:
Confirmed the package includes:
theme/Root.jstheme/MarkdownActionsDropdown/index.jsSwizzle portability validation
Verified the root cause of the consumer error:
Adjusted the implementation so the generated consumer file is self-contained.
Example consumer workflow after this PR
Install/update the plugin
Swizzle the dropdown:
Edit:
Customize labels, icons, menu items, analytics, or behavior as needed
To sum up / Changelog summary
Changed
MarkdownActionsDropdownas a first-class Docusaurus theme component.Rootto render@theme/MarkdownActionsDropdownso consumer overrides are picked up automatically.MarkdownActionsDropdownas the supported swizzle target instead ofRoot.Fixed
theme/MarkdownActionsDropdownself-contained so swizzled copies do not fail to build in consumer sites due to plugin-local relative imports.I've also bumped the version number to
2.3.0since it adds a new feature.Thanks!