mirror of
https://github.com/ankitects/anki.git
synced 2026-07-28 07:58:45 -04:00
## Summary - add a generated `docs-site/` Mintlify proof of concept for a unified Anki docs site - migrate the desktop manual, AnkiMobile docs, FAQs, add-on docs, translation docs, release notes, legacy docs, and repo-local Sphinx/MyST developer docs into the POC tree - add a migration helper that preserves mdBook ordering, handles common MDX incompatibilities, and regenerates the landing-page-inspired Mintlify styling - apply minimal styling based on the current Anki landing page: Anki logo, Hanken Grotesk, blue primary color, subtle surfaces, and compact nav treatment ## Validation - `uv run --with ty ty check tools/mintlify_poc_migrate.py` - `source ~/.nvm/nvm.sh && nvm use 22.15.0 && mint validate` - previewed locally with `mint dev --port 3000` and checked the home page/developer docs in browser ## Notes This is intentionally a draft POC. It does not remove the existing Sphinx or mdBook docs flows yet; it demonstrates what bringing the sources into this repo and building from a single Mintlify root could look like. --------- Co-authored-by: Andrew Sanchez <andrewsanchez@users.noreply.github.com> Co-authored-by: Luc Mcgrady <lucmcgrady@gmail.com> Co-authored-by: Abdo <abdo@abdnh.net>
98 lines
3.1 KiB
Plaintext
98 lines
3.1 KiB
Plaintext
---
|
||
title: "Monkey Patching and Method Wrapping"
|
||
---
|
||
|
||
If you want to modify a function that doesn’t already have a hook, it’s
|
||
possible to overwrite that function with a custom version instead. This
|
||
is sometimes referred to as 'monkey patching'.
|
||
|
||
Monkey patching is useful in the testing stage, and while waiting for
|
||
new hooks to be integrated into Anki. But please don’t rely on it long
|
||
term, as monkey patching is very fragile, and will tend to break as Anki
|
||
is updated in the future.
|
||
|
||
The only exception to the above is if you’re making extensive changes to
|
||
Anki where adding new hooks would be impractical. In that case, you may
|
||
unfortunately need to modify your add-on periodically as Anki is
|
||
updated.
|
||
|
||
In
|
||
[aqt/editor.py](https://github.com/ankitects/anki/blob/main/qt/aqt/editor.py)
|
||
there is a function setupButtons() which creates the buttons like
|
||
bold, italics and so on that you see in the editor. Let’s imagine you
|
||
want to add another button in your add-on.
|
||
|
||
Anki 2.1 no longer uses setupButtons(). The code below is still useful
|
||
to understand how monkey patching works, but for adding buttons to the
|
||
editor please see the setupEditorButtons hook described in the previous
|
||
section.
|
||
|
||
The simplest way is to copy and paste the function from the Anki source
|
||
code, add your text to the bottom, and then overwrite the original, like
|
||
so:
|
||
|
||
```python
|
||
from aqt.editor import Editor
|
||
|
||
def mySetupButtons(self):
|
||
<copy & pasted code from original>
|
||
<custom add-on code>
|
||
|
||
Editor.setupButtons = mySetupButtons
|
||
```
|
||
|
||
This approach is fragile however, as if the original code is updated in
|
||
a future version of Anki, you would also have to update your add-on. A
|
||
better approach would be to save the original, and call it in our custom
|
||
version:
|
||
|
||
```python
|
||
from aqt.editor import Editor
|
||
|
||
def mySetupButtons(self):
|
||
origSetupButtons(self)
|
||
<custom add-on code>
|
||
|
||
origSetupButtons = Editor.setupButtons
|
||
Editor.setupButtons = mySetupButtons
|
||
```
|
||
|
||
Because this is a common operation, Anki provides a function called
|
||
wrap() which makes this a little more convenient. A real example:
|
||
|
||
```python
|
||
from anki.hooks import wrap
|
||
from aqt.editor import Editor
|
||
from aqt.utils import showInfo
|
||
|
||
def buttonPressed(self):
|
||
showInfo("pressed " + `self`)
|
||
|
||
def mySetupButtons(self):
|
||
# - size=False tells Anki not to use a small button
|
||
# - the lambda is necessary to pass the editor instance to the
|
||
# callback, as we're passing in a function rather than a bound
|
||
# method
|
||
self._addButton("mybutton", lambda s=self: buttonPressed(self),
|
||
text="PressMe", size=False)
|
||
|
||
Editor.setupButtons = wrap(Editor.setupButtons, mySetupButtons)
|
||
```
|
||
|
||
By default, wrap() runs your custom code after the original code. You
|
||
can pass a third argument, "before", to reverse this. If you need to run
|
||
code both before and after the original version, you can do so like so:
|
||
|
||
```python
|
||
from anki.hooks import wrap
|
||
from aqt.editor import Editor
|
||
|
||
def mySetupButtons(self, _old):
|
||
<before code>
|
||
ret = _old(self)
|
||
<after code>
|
||
return ret
|
||
|
||
Editor.setupButtons = wrap(Editor.setupButtons, mySetupButtons, "around")
|
||
```
|