style: format the repository with prettier

These files were already out of step with the project's Prettier config
before this branch of work; running `pnpm format` finally swept them up.
No semantic changes.

Kept separate from the functional commits so the reformatting does not
bury them in diff noise.
This commit is contained in:
zihluwang committed 2026-09-25 15:37:59 +08:00
1 parent 6800f7251d
commit 861852961f
50 files changed
+643 -678

No files matched your search

+2 -2
View File
@@ -11,7 +11,7 @@ author:
## When to Add Seasonings
| Seasoning Type | Timing | Suitable Dishes | Effect |
|----------------------------------------|----------------------------------------|------------------------------------------------------|-------------------------------------------------------------------------------|
| -------------------------------------- | -------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------- |
| **Salt** | Last | Leafy greens | Prevents leaves from wilting and releasing water, keeps them crisp and tender |
| | Mid-way | Shredded potatoes, green beans, garlic shoots | Better flavour absorption |
| **MSG, Light Soy Sauce, Oyster Sauce** | Towards the end | Dishes needing umami and aroma enhancement | Adds umami and aroma; high heat destroys freshness and fragrance |
@@ -24,7 +24,7 @@ author:
## Quick Reference
| Seasoning | Timing | Effect | Example |
|-----------------------------------------------|------------------------------|-----------------------------------------------------------------------------|---------------------------------------------------------------------------|
| --------------------------------------------- | ---------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| **Salt** | 10–15 seconds before serving | Prevents premature water loss and wilting of leafy greens; keeps them crisp | Sprinkle salt and toss before turning off the heat for lettuce or spinach |
| **Minced Garlic / Ginger** | First, after oil is hot | Releases fragrance and enhances flavour | Sauté minced garlic in hot oil, then add greens |
| **Light Soy Sauce / Oyster Sauce** (optional) | After salt | Adds umami; use sparingly to avoid overpowering the vegetables | Add 1–2 drops of light soy sauce after salting Shanghai greens |
@@ -17,13 +17,13 @@ author:
```javascript
function processResponse(response) {
if (response.status === 200 && response.data) {
return { success: true, data: response.data };
return { success: true, data: response.data }
} else if (response.status === 404) {
return { success: false, error: 'Not found' };
return { success: false, error: "Not found" }
} else if (response.status >= 500) {
return { success: false, error: 'Server error' };
return { success: false, error: "Server error" }
} else {
return { success: false, error: 'Unknown error' };
return { success: false, error: "Unknown error" }
}
}
```
+3 -3
View File
@@ -19,11 +19,11 @@ sound more confident and professional.
## Scenario Cheatsheet
| Scenario | ❌ Don't Use (sounds…) | ✅ Use Instead (sounds…) | Why It Works |
|----------------------------|----------------------------------------------|-----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Scenario | ❌ Don't Use (sounds…) | ✅ Use Instead (sounds…) | Why It Works |
| -------------------------- | -------------------------------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Late reply | **Sorry for the delay** | **Thanks for your patience** | Swaps an apology for gratitude — the focus shifts from "I was wrong" to "you were generous," acknowledging the delay while making the recipient feel respected |
| Scheduling | **What works best for you?** | **Could you do …?** | The former throws the decision entirely back to the other person; the latter offers a concrete option, cutting down on back-and-forth |
| After helping someone | **No problem / No worries** | **Always happy to help** | The former implies the task *could* have been a problem; the latter signals you enjoyed it and would happily do it again |
| After helping someone | **No problem / No worries** | **Always happy to help** | The former implies the task _could_ have been a problem; the latter signals you enjoyed it and would happily do it again |
| Making a suggestion | **I think maybe we should …** | **It'd be best if we …** | The former oozes hesitation and self-doubt; the latter delivers a clear judgment — like someone with experience making a decision |
| Text isn't working | **_Spending 30 minutes rewriting an email_** | **It'd be easier to discuss in person** | Recognising the medium itself is the bottleneck and switching channels can be the most efficient move |
| Checking for understanding | **Hopefully that makes sense?** | **Let me know if you have questions** | The former betrays doubt about your own clarity; the latter calmly shares responsibility — the reader now has an action item too |
@@ -8,7 +8,7 @@ tags:
---
> This article was originally written by **落格博客
**: [落格博客](https://www.logcg.com/) » [Frequent Wake-from-Sleep Issues After Upgrading to macOS Monterey](https://www.logcg.com/archives/3528.html)
> **: [落格博客](https://www.logcg.com/) » [Frequent Wake-from-Sleep Issues After Upgrading to macOS Monterey](https://www.logcg.com/archives/3528.html)
After upgrading to macOS Monterey, my screen kept lighting up in the middle of the night for no apparent reason. It had
happened before, but only when notifications came in. Now the screen lights up on its own with no trigger — same
@@ -33,8 +33,8 @@ So for Power Nap, we have to go through the command line. First, check the curre
Also check **`tcpkeepalive`** — it likely isn't 0 either and should also be turned off. It controls whether your Mac
maintains TCP connections while sleeping. Run **`sudo pmset -a tcpkeepalive 0`** — you'll see a terminal warning:
***Warning: This option disables TCP Keep Alive mechanism when system is sleeping. This will result in some critical
features like 'Find My Mac' not to function properly.***
**_Warning: This option disables TCP Keep Alive mechanism when system is sleeping. This will result in some critical
features like 'Find My Mac' not to function properly._**
Essentially, turning it off limits some features — the system simply won't connect to the network while asleep. I'm
fairly confident that if someone actually steals your Mac, they won't be getting it online anyway.
@@ -10,8 +10,8 @@ author:
email: real@zihluwang.me
---
| Chinese Size Name | English Point Size (pt) | mm | px |
|--------------------|-------------------------|-------|------|
| Chinese Size Name | English Point Size (pt) | mm | px |
| -------------------- | ----------------------- | ----- | ---- |
| 初号 (Primary) | 42 | 14.82 | 56 |
| 小初 (Small Primary) | 36 | 12.7 | 48 |
| 一号 (No. 1) | 26 | 9.17 | 34.7 |
@@ -23,9 +23,9 @@ author:
- **Axios Instance**: Create a centralised Axios instance for API calls to apply common configuration (base URL,
headers, interceptors).
- **Interceptors**: Use Axios interceptors to:
- Add authentication tokens to outgoing requests.
- Handle global error responses (e.g., display a notification for `401 Unauthorized`).
- Log requests/responses in development environments.
- Add authentication tokens to outgoing requests.
- Handle global error responses (e.g., display a notification for `401 Unauthorized`).
- Log requests/responses in development environments.
- **Error Handling**: Centralise API error handling in Axios interceptors or custom utility functions to provide
consistent user feedback.
@@ -34,14 +34,14 @@ author:
- **Function Components & Hooks**: Prefer function components with React Hooks over class components for new
development.
- **Props**:
- Define `interface` or `type` for component props to ensure type safety.
- Destructure props at the component entry point for clarity.
- Define `interface` or `type` for component props to ensure type safety.
- Destructure props at the component entry point for clarity.
- **State Management (Redux)**:
- Use Redux Toolkit for efficient, boilerplate-reduced Redux development.
- Use `createSlice` to organise Redux logic into "slices" (feature-specific reducers, actions, and selectors).
- Follow the "ducks" pattern or "slices" approach to co-locate Redux logic.
- Use Redux Toolkit for efficient, boilerplate-reduced Redux development.
- Use `createSlice` to organise Redux logic into "slices" (feature-specific reducers, actions, and selectors).
- Follow the "ducks" pattern or "slices" approach to co-locate Redux logic.
- **Component Composition**: Break down complex UIs into smaller, reusable, single-responsibility components.
- **Ant Design**:
- Leverage Ant Design components for consistent UI/UX.
- Use CSS-in-JS solutions to consistently customise Ant Design themes and styles across the application if needed.
- Leverage Ant Design components for consistent UI/UX.
- Use CSS-in-JS solutions to consistently customise Ant Design themes and styles across the application if needed.
- **Accessibility**: Design and implement components with web accessibility (a11y) in mind from the start.
+1 -1
View File
@@ -16,7 +16,7 @@ variable in the code. Simplified Chinese sits at 84% and Traditional Chinese at
Navigate to `/path/to/gitlab/embedded/service/gitlab-rails/app/helpers/preferred_language_switcher_helper.rb` and modify
the code as follows:
```diff title="/path/to/gitlab/embedded/service/gitlab-rails/app/helpers/preferred_language_switcher_helper.rb"
```diff title="/path/to/gitlab/embedded/service/gitlab-rails/app/helpers/preferred_language_switcher_helper.rb"
- SWITCHER_MINIMUM_TRANSLATION_LEVEL = 90
+ SWITCHER_MINIMUM_TRANSLATION_LEVEL = 80
```
@@ -105,7 +105,7 @@ The N+1 problem occurs when JPA executes one query for the parent entity, then N
**Fixes:**
| Approach | When to use |
|--------------------------|---------------------------------------------------|
| ------------------------ | ------------------------------------------------- |
| `@EntityGraph` | Declarative, good for entity-specific fetch plans |
| `JOIN FETCH` in `@Query` | Fine-grained control per query |
| `@BatchSize` | Reduces N+1 to N/k+1 by batching |
@@ -144,6 +144,7 @@ This happens when you access a lazily-loaded association outside the persistence
@Query("SELECT new com.example.UserDto(u.id, u.name) FROM User u WHERE u.id = :id")
UserDto findUserDtoById(@Param("id") long id);
```
3. **`@Transactional(readOnly = true)`** on the service method — keep the session open for the entire method scope.
### When should I use `@Transactional(readOnly = true)`?
@@ -275,7 +276,7 @@ Note that `@JsonAnyGetter` must be placed on the **getter method**, not the fiel
### How to choose
| Scenario | Annotation |
|-------------------------------------------------------|--------------------|
| Flatten nested objects with fixed fields (e.g. address, config) | `@JsonUnwrapped` |
| Flatten dynamic key-value pairs with unknown keys | `@JsonAnyGetter` |
| Scenario | Annotation |
| --------------------------------------------------------------- | ---------------- |
| Flatten nested objects with fixed fields (e.g. address, config) | `@JsonUnwrapped` |
| Flatten dynamic key-value pairs with unknown keys | `@JsonAnyGetter` |
@@ -98,7 +98,6 @@ author:
## Spring Boot Best Practices & Layered Architecture
- **Layered Architecture (MVC with Manager Layer)**: Our backend applications follow a strict multi-layered architecture, ensuring clear separation of responsibilities and improving maintainability and testability. The layers and their responsibilities are:
- **Controller Layer**: Located in the `controller` package. Responsible for exposing RESTful APIs, handling HTTP requests, and mapping request parameters/bodies to service layer calls. Controllers should remain lightweight, focusing primarily on input validation (using DTOs) and coordinating calls to the `Service` layer.
- **Service Layer**: Located in the `service` package. This layer encapsulates core business logic. Services expose a directly consumable API to the `Controller` layer, abstracting business processes and transaction management. Services coordinate calls to the `Manager` layer to execute business operations.
- **Manager Layer**: Located in the `manager` package. This layer provides atomic business operations that can be composed by the `Service` layer. Managers typically handle more complex business logic and may involve interacting with multiple repositories or other external systems at a finer granularity.
@@ -120,7 +119,7 @@ author:
- Data operation conventions:
- Use JPA for simple database operations.
- Use MyBatis for complex database operations.
- When performing paginated queries, page numbers should start from 0 (*compatible with Spring Data JPA*).
- When performing paginated queries, page numbers should start from 0 (_compatible with Spring Data JPA_).
- **Data Access Method Naming Conventions**:
- For **querying data lists**: methods **must** start with `selectListBy`, followed by the filter criteria (e.g., `selectListByUserId`, `selectListByDepartmentIdAndStatus`). These methods must also include a `PageRequest` parameter for pagination.
- For querying **single data records**: methods **must** start with `selectOne` (e.g., `selectOneById`, `selectOneByUsername`).
+2 -2
View File
@@ -5,8 +5,8 @@ tags:
- json
- database
author:
name: Zihlu Wang
email: real@zihluwang.me
name: Zihlu Wang
email: real@zihluwang.me
---
MySQL (since version 5.7) **does not directly support a data type called `jsonb`**. `jsonb` is a data type specific to PostgreSQL, which stores JSON data in a binary format with pre-parsing for faster access and manipulation during queries.
+6 -7
View File
@@ -26,11 +26,11 @@ https://gravatar.com/avatar/<hash>
### Node.js
```js
import { createHash } from "node:crypto";
import { createHash } from "node:crypto"
const email = "user@example.com".trim().toLowerCase();
const hash = createHash("sha256").update(email).digest("hex");
const url = `https://gravatar.com/avatar/${hash}`;
const email = "user@example.com".trim().toLowerCase()
const hash = createHash("sha256").update(email).digest("hex")
const url = `https://gravatar.com/avatar/${hash}`
```
### Python
@@ -54,7 +54,7 @@ echo -n "user@example.com" | tr '[:upper:]' '[:lower:]' | sha256sum | cut -d ' '
The `/avatar/` endpoint accepts several query parameters to customise the result:
| Parameter | Description | Example |
|-----------|-----------------------------------------|----------------|
| --------- | --------------------------------------- | -------------- |
| `s` | Size in pixels (default: 80) | `?s=200` |
| `d` | Default image when no Gravatar is found | `?d=identicon` |
| `r` | Content rating (`g`, `pg`, `r`, `x`) | `?r=g` |
@@ -77,8 +77,7 @@ The `/avatar/` endpoint accepts several query parameters to customise the result
src="https://gravatar.com/avatar/a3b4c5d6e7f8?s=160&d=robohash&r=g"
alt="User avatar"
width="160"
height="160"
/>
height="160" />
```
Always pass the `d` parameter to avoid broken images for users who have not set up a Gravatar. `identicon` and
@@ -7,7 +7,7 @@ title: Calendar Toolbox API
The library is organised under the base package `com.onixbyte.calendar` with the following structure:
| Package | Description |
|--------------------------------------------|--------------------------------------------|
| ------------------------------------------ | ------------------------------------------ |
| `com.onixbyte.calendar` | Root calendar object |
| `com.onixbyte.calendar.component` | iCalendar components (VEVENT, VTODO, etc.) |
| `com.onixbyte.calendar.component.property` | Component-level properties |
@@ -47,7 +47,7 @@ String icsContent = calendar.formatted();
All calendar-level properties live in `com.onixbyte.calendar.property` and implement `CalendarProperty`.
| Class | iCalendar Property | Description |
|--------------------------|----------------------|-------------------------------------------|
| ------------------------ | -------------------- | ----------------------------------------- |
| `CalendarScale` | `CALSCALE` | Calendar system (e.g., GREGORIAN) |
| `Method` | `METHOD` | iCalendar method (e.g., PUBLISH, REQUEST) |
| `ProductIdentifier` | `PRODID` | Product identifier of the calendar |
@@ -277,7 +277,7 @@ Alarm emailAlarm = Alarm.builder()
Component properties live in `com.onixbyte.calendar.component.property` and implement `ComponentProperty`.
| Class | iCalendar Property | Description |
|---------------------------|--------------------|----------------------------------------------------------|
| ------------------------- | ------------------ | -------------------------------------------------------- |
| `Action` | `ACTION` | Alarm action type (AUDIO, DISPLAY, EMAIL) |
| `Attachment` | `ATTACH` | Document attachment |
| `Attendee` | `ATTENDEE` | Event/task attendee |
@@ -328,7 +328,7 @@ Component properties live in `com.onixbyte.calendar.component.property` and impl
Parameters in `com.onixbyte.calendar.parameter` provide additional qualifiers on component properties.
| Class | iCalendar Parameter | Description |
|-------------------------------|---------------------|--------------------------------------------------------|
| ----------------------------- | ------------------- | ------------------------------------------------------ |
| `AlarmTriggerRelationship` | `RELATED` | Trigger relationship (START, END) |
| `AlternateTextRepresentation` | `ALTREP` | Alternate text URI |
| `CalendarUserType` | `CUTYPE` | Calendar user type (INDIVIDUAL, GROUP, RESOURCE, etc.) |
@@ -357,7 +357,7 @@ Parameters in `com.onixbyte.calendar.parameter` provide additional qualifiers on
Located in `com.onixbyte.calendar.recurrence`.
| Class | Description |
|--------------|---------------------------------------------------------------------------|
| ------------ | ------------------------------------------------------------------------- |
| `Frequency` | Frequency constants (DAILY, WEEKLY, MONTHLY, YEARLY) for recurrence rules |
| `WeekdayNum` | Weekday number for recurrence rules (e.g., 2nd Monday) |
@@ -368,7 +368,7 @@ Located in `com.onixbyte.calendar.recurrence`.
Located in `com.onixbyte.calendar.value`.
| Class | Description |
|---------------------|------------------------------------------------|
| ------------------- | ---------------------------------------------- |
| `FreeBusyTimeValue` | Represents free/busy time value |
| `PeriodOfTime` | Represents a period of time with start and end |
| `PropertyValue` | Base value type for properties |
@@ -22,10 +22,8 @@ With Calendar Toolbox, you can effortlessly create, customise, and export calend
<Tabs>
<Tab label="Gradle with Kotlin DSL">
```kotlin title="build.gradle.kts"
dependencies {
implementation("com.onixbyte:calendar-toolbox:1.1.0")
}
```kotlin title="build.gradle.kts" dependencies{" "}
{implementation("com.onixbyte:calendar-toolbox:1.1.0")}
```
</Tab>
<Tab label="Maven">
+51 -51
View File
@@ -6,19 +6,19 @@ title: Captcha API
The library is organised under the base package `com.onixbyte.captcha` with the following structure:
| Package | Description |
|---------------------------------------------|---------------------------------------|
| `com.onixbyte.captcha` | Core interfaces |
| `com.onixbyte.captcha.impl` | Default implementations |
| `com.onixbyte.captcha.text` | Text producer and renderer interfaces |
| `com.onixbyte.captcha.text.impl` | Text producer and renderer impls |
| `com.onixbyte.captcha.text.enums` | Text-related enums |
| `com.onixbyte.captcha.background` | Background producer interface |
| `com.onixbyte.captcha.background.impl` | Background producer implementations |
| `com.onixbyte.captcha.noise` | Noise producer interface |
| `com.onixbyte.captcha.noise.impl` | Noise producer implementations |
| `com.onixbyte.captcha.gimpy` | Distortion engine interface |
| `com.onixbyte.captcha.gimpy.impl` | Distortion engine implementations |
| Package | Description |
| -------------------------------------- | ------------------------------------- |
| `com.onixbyte.captcha` | Core interfaces |
| `com.onixbyte.captcha.impl` | Default implementations |
| `com.onixbyte.captcha.text` | Text producer and renderer interfaces |
| `com.onixbyte.captcha.text.impl` | Text producer and renderer impls |
| `com.onixbyte.captcha.text.enums` | Text-related enums |
| `com.onixbyte.captcha.background` | Background producer interface |
| `com.onixbyte.captcha.background.impl` | Background producer implementations |
| `com.onixbyte.captcha.noise` | Noise producer interface |
| `com.onixbyte.captcha.noise.impl` | Noise producer implementations |
| `com.onixbyte.captcha.gimpy` | Distortion engine interface |
| `com.onixbyte.captcha.gimpy.impl` | Distortion engine implementations |
---
@@ -45,17 +45,17 @@ BufferedImage image = captcha.createImage(text);
### DefaultCaptchaProducer Builder
| Method | Default Value | Description |
|---------------------|---------------------------------------------|---------------------------------------|
| `textProducer` | `DefaultTextProducer.builder().build()` | The text producer to use |
| `wordRenderer` | `DefaultWordRenderer.builder().build()` | The word renderer to use |
| `gimpyEngine` | `WaterRipple.builder().build()` | The distortion engine to use |
| `backgroundProducer`| `DefaultBackgroundProducer.builder().build()`| The background producer to use |
| `width` | `200` | Width of the CAPTCHA image |
| `height` | `50` | Height of the CAPTCHA image |
| `borderDrawn` | `true` | Whether a border is drawn |
| `borderColour` | `Color.BLACK` | The colour of the border |
| `borderThickness` | `1` | The thickness of the border |
| Method | Default Value | Description |
| -------------------- | --------------------------------------------- | ------------------------------ |
| `textProducer` | `DefaultTextProducer.builder().build()` | The text producer to use |
| `wordRenderer` | `DefaultWordRenderer.builder().build()` | The word renderer to use |
| `gimpyEngine` | `WaterRipple.builder().build()` | The distortion engine to use |
| `backgroundProducer` | `DefaultBackgroundProducer.builder().build()` | The background producer to use |
| `width` | `200` | Width of the CAPTCHA image |
| `height` | `50` | Height of the CAPTCHA image |
| `borderDrawn` | `true` | Whether a border is drawn |
| `borderColour` | `Color.BLACK` | The colour of the border |
| `borderThickness` | `1` | The thickness of the border |
---
@@ -82,10 +82,10 @@ DefaultTextProducer textProducer = DefaultTextProducer.builder()
.build();
```
| Method | Default Value | Description |
|----------|-----------------------------------------------------------|--------------------------------|
| `length` | `6` | Length of generated text |
| `chars` | `a-z`, `A-Z`, `0-9` (62 characters) | Characters used for generation |
| Method | Default Value | Description |
| -------- | ----------------------------------- | ------------------------------ |
| `length` | `6` | Length of generated text |
| `chars` | `a-z`, `A-Z`, `0-9` (62 characters) | Characters used for generation |
### WordRenderer
@@ -111,24 +111,24 @@ DefaultWordRenderer wordRenderer = DefaultWordRenderer.builder()
.build();
```
| Method | Default Value | Description |
|-------------|-----------------------------------|-----------------------------------------|
| `fontSize` | `40` | Font size in pixels |
| `fonts` | `["Arial", "Courier"]` | Font families to use (randomly chosen) |
| `fontColour`| `Color.BLACK` | Font colour |
| `charSpace` | `2` | Space between characters in pixels |
| `fontStyle` | `FontStyle.BOLD` | Font style to apply |
| Method | Default Value | Description |
| ------------ | ---------------------- | -------------------------------------- |
| `fontSize` | `40` | Font size in pixels |
| `fonts` | `["Arial", "Courier"]` | Font families to use (randomly chosen) |
| `fontColour` | `Color.BLACK` | Font colour |
| `charSpace` | `2` | Space between characters in pixels |
| `fontStyle` | `FontStyle.BOLD` | Font style to apply |
### FontStyle
Defines the supported font styles for rendering CAPTCHA text.
| Value | Corresponding AWT Constant | Description |
|---------------|-------------------------------------|------------------------------|
| `PLAIN` | `java.awt.Font.PLAIN` | Plain style |
| `BOLD` | `java.awt.Font.BOLD` | Bold style |
| `ITALIC` | `java.awt.Font.ITALIC` | Italic style |
| `BOLD_ITALIC` | `java.awt.Font.BOLD | Font.ITALIC` | Bold and italic combined |
| Value | Corresponding AWT Constant | Description |
| ------------- | -------------------------- | ------------ | ------------------------ |
| `PLAIN` | `java.awt.Font.PLAIN` | Plain style |
| `BOLD` | `java.awt.Font.BOLD` | Bold style |
| `ITALIC` | `java.awt.Font.ITALIC` | Italic style |
| `BOLD_ITALIC` | `java.awt.Font.BOLD | Font.ITALIC` | Bold and italic combined |
---
@@ -152,9 +152,9 @@ WaterRipple gimpy = WaterRipple.builder()
.build();
```
| Method | Default Value | Description |
|-----------------|---------------------------------------------|------------------------------|
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | The noise producer to use |
| Method | Default Value | Description |
| --------------- | ---------------------------------------- | ------------------------- |
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | The noise producer to use |
### FishEyeGimpy
@@ -175,9 +175,9 @@ ShadowGimpy gimpy = ShadowGimpy.builder()
.build();
```
| Method | Default Value | Description |
|-----------------|---------------------------------------------|------------------------------|
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | The noise producer to use |
| Method | Default Value | Description |
| --------------- | ---------------------------------------- | ------------------------- |
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | The noise producer to use |
---
@@ -204,9 +204,9 @@ DefaultNoiseProducer noise = DefaultNoiseProducer.builder()
.build();
```
| Method | Default Value | Description |
|---------------|---------------|---------------------|
| `noiseColour` | `Color.BLACK` | The noise colour |
| Method | Default Value | Description |
| ------------- | ------------- | ---------------- |
| `noiseColour` | `Color.BLACK` | The noise colour |
#### NoNoiseProducer
@@ -243,6 +243,6 @@ DefaultBackgroundProducer background = DefaultBackgroundProducer.builder()
```
| Method | Default Value | Description |
|--------------|--------------------|---------------------------------|
| ------------ | ------------------ | ------------------------------- |
| `colourFrom` | `Color.LIGHT_GRAY` | The starting colour of gradient |
| `colourTo` | `Color.WHITE` | The ending colour of gradient |
@@ -23,10 +23,7 @@ With Captcha, you can easily generate customisable CAPTCHA images with various d
<Tabs>
<Tab label="Gradle with Kotlin DSL">
```kotlin title="build.gradle.kts"
dependencies {
implementation("com.onixbyte:captcha:1.0.0")
}
```kotlin title="build.gradle.kts" dependencies {implementation("com.onixbyte:captcha:1.0.0")}
```
</Tab>
<Tab label="Maven">
@@ -23,6 +23,7 @@ Skills are deployed directly into Claude Code's own skills directory (`~/.claude
| Windows (amd64) | `ccsm-windows-amd64.exe` |
Place the binary somewhere on your `PATH` and rename it to `ccsm` (or `ccsm.exe` on Windows).
</Tab>
<Tab label="Cargo install">
```bash
@@ -109,10 +110,10 @@ ccsm marketplace remove my-marketplace
CCSM supports two deploy modes:
| Mode | Behaviour | Use case |
|------|-----------|----------|
| `copy` (default) | Files are physically copied to `~/.claude/skills/<name>/` | Normal use — safe and self-contained |
| `link` | A symlink is created pointing to the local store | Skill development — changes to source files are picked up immediately |
| Mode | Behaviour | Use case |
| ---------------- | --------------------------------------------------------- | --------------------------------------------------------------------- |
| `copy` (default) | Files are physically copied to `~/.claude/skills/<name>/` | Normal use — safe and self-contained |
| `link` | A symlink is created pointing to the local store | Skill development — changes to source files are picked up immediately |
Set the default mode in your config, or override per install:
@@ -158,21 +159,21 @@ your-marketplace-repo/
**Top-level fields:**
| Field | Required | Description |
|-------|----------|-------------|
| `name` | Yes | Marketplace display name |
| `version` | No | Arbitrary version string for your own tracking |
| `skills` | No | Array of skill entries (defaults to `[]`) |
| Field | Required | Description |
| --------- | -------- | ---------------------------------------------- |
| `name` | Yes | Marketplace display name |
| `version` | No | Arbitrary version string for your own tracking |
| `skills` | No | Array of skill entries (defaults to `[]`) |
**Skill entry fields:**
| Field | Required | Description |
|-------|----------|-------------|
| `name` | Yes | Unique skill identifier (used with `ccsm install <name>`) |
| `description` | Yes | One-line summary shown in `ccsm search` output |
| `repository` | Yes | Public Git repository URL for the skill |
| `branch` | No | Git branch to install from (tries `main` first, falls back to `master`) |
| `path` | No | Subdirectory within the repository where the skill files live — enables monorepos hosting multiple skills |
| Field | Required | Description |
| ------------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `name` | Yes | Unique skill identifier (used with `ccsm install <name>`) |
| `description` | Yes | One-line summary shown in `ccsm search` output |
| `repository` | Yes | Public Git repository URL for the skill |
| `branch` | No | Git branch to install from (tries `main` first, falls back to `master`) |
| `path` | No | Subdirectory within the repository where the skill files live — enables monorepos hosting multiple skills |
### How it works
@@ -202,12 +203,12 @@ my-skill-repo/
## How CCSM Stores Data
| Path | Purpose |
|------|---------|
| `~/.claude/skills/` | Claude Code's skills directory — where skills are deployed |
| `~/.config/ccsm/config.json` | CCSM configuration (registered marketplaces, default mode) |
| `~/.config/ccsm/marketplaces/` | Cached marketplace manifests |
| `~/.config/ccsm/skills/` | Downloaded skill files (local store) |
| Path | Purpose |
| ------------------------------ | ---------------------------------------------------------- |
| `~/.claude/skills/` | Claude Code's skills directory — where skills are deployed |
| `~/.config/ccsm/config.json` | CCSM configuration (registered marketplaces, default mode) |
| `~/.config/ccsm/marketplaces/` | Cached marketplace manifests |
| `~/.config/ccsm/skills/` | Downloaded skill files (local store) |
On Windows, `~/.config/` resolves to `C:\Users\<user>\AppData\Roaming\`.
@@ -6,64 +6,64 @@ title: Delta Force Guide API
The backend is a Spring Boot 3 application organised under the base package `com.onixbyte.deltaforceguide`:
| Package | Description |
|---------------------------------------------|-----------------------------------|
| `controller` | REST API endpoint controllers |
| `service` | Business logic layer |
| `repository` | MyBatis data access layer |
| `domain` | JPA entity and domain objects |
| `config` | Spring configuration (security, cache, etc.) |
| `properties` | Configuration property classes |
| `enumeration` | Enumerated types |
| `shared` | Shared utilities |
| Package | Description |
| ------------- | -------------------------------------------- |
| `controller` | REST API endpoint controllers |
| `service` | Business logic layer |
| `repository` | MyBatis data access layer |
| `domain` | JPA entity and domain objects |
| `config` | Spring configuration (security, cache, etc.) |
| `properties` | Configuration property classes |
| `enumeration` | Enumerated types |
| `shared` | Shared utilities |
## API Endpoints
### Authentication
| Method | Path | Description | Auth |
|--------|-----------------------|--------------------------|------|
| `POST` | `/api/auth/login` | Log in with credentials | No |
| `POST` | `/api/auth/refresh` | Refresh access token | No |
| `GET` | `/api/auth/profile` | Get current user profile | Yes |
| Method | Path | Description | Auth |
| ------ | ------------------- | ------------------------ | ---- |
| `POST` | `/api/auth/login` | Log in with credentials | No |
| `POST` | `/api/auth/refresh` | Refresh access token | No |
| `GET` | `/api/auth/profile` | Get current user profile | Yes |
### Firearms
| Method | Path | Description |
|----------|-----------------------|--------------------------|
| `GET` | `/api/firearms` | List firearms (paginated, filterable by type) |
| `GET` | `/api/firearms/:id` | Get firearm by ID |
| `POST` | `/api/firearms` | Create a new firearm |
| `PUT` | `/api/firearms/:id` | Update an existing firearm |
| `DELETE` | `/api/firearms/:id` | Remove a firearm |
| Method | Path | Description |
| -------- | ------------------- | --------------------------------------------- |
| `GET` | `/api/firearms` | List firearms (paginated, filterable by type) |
| `GET` | `/api/firearms/:id` | Get firearm by ID |
| `POST` | `/api/firearms` | Create a new firearm |
| `PUT` | `/api/firearms/:id` | Update an existing firearm |
| `DELETE` | `/api/firearms/:id` | Remove a firearm |
### Modifications
| Method | Path | Description |
|----------|-----------------------------------|--------------------------------|
| Method | Path | Description |
| -------- | --------------------------------- | -------------------------------------------------------------- |
| `GET` | `/api/modifications` | List modifications (paginated, filterable by firearm and tags) |
| `GET` | `/api/modifications/:id` | Get modification by ID |
| `POST` | `/api/modifications` | Create a modification |
| `POST` | `/api/modifications/batch` | Batch create modifications |
| `PUT` | `/api/modifications/:id` | Update a modification |
| `DELETE` | `/api/modifications/:id` | Remove a modification |
| `DELETE` | `/api/modifications/batch-delete` | Batch remove modifications |
| `GET` | `/api/modifications/:id` | Get modification by ID |
| `POST` | `/api/modifications` | Create a modification |
| `POST` | `/api/modifications/batch` | Batch create modifications |
| `PUT` | `/api/modifications/:id` | Update a modification |
| `DELETE` | `/api/modifications/:id` | Remove a modification |
| `DELETE` | `/api/modifications/batch-delete` | Batch remove modifications |
### Tags
| Method | Path | Description |
|--------|-----------------------|-----------------------|
| `GET` | `/api/tags` | List all tags |
| Method | Path | Description |
| ------ | ----------- | ------------- |
| `GET` | `/api/tags` | List all tags |
## Frontend Routes
| Path | Layout | Page | Description |
|---------------|-------------|-------------------|---------------------------------|
| `/` | Hero Layout | Firearms Browser | Home page — firearm list |
| `/firearms` | Hero Layout | Firearms Browser | Firearm detail and search |
| `/mod-codes` | Hero Layout | Modification Codes| Modification code library |
| `/legal` | Hero Layout | Legal | Legal and privacy information |
| `/login` | Empty Layout| Login | User authentication page |
| Path | Layout | Page | Description |
| ------------ | ------------ | ------------------ | ----------------------------- |
| `/` | Hero Layout | Firearms Browser | Home page — firearm list |
| `/firearms` | Hero Layout | Firearms Browser | Firearm detail and search |
| `/mod-codes` | Hero Layout | Modification Codes | Modification code library |
| `/legal` | Hero Layout | Legal | Legal and privacy information |
| `/login` | Empty Layout | Login | User authentication page |
## Frontend State Management
@@ -82,10 +82,10 @@ The frontend uses a shared `WebClient` wrapper around Axios that handles:
## Infrastructure
| Component | Technology |
|---------------|-----------------------------|
| Database | PostgreSQL (with Flyway migrations) |
| Cache | Redis (session/token storage) |
| File Storage | AWS S3 (firearm images) |
| Containerisation | Docker |
| Deployment | Docker Compose behind Nginx |
| Component | Technology |
| ---------------- | ----------------------------------- |
| Database | PostgreSQL (with Flyway migrations) |
| Cache | Redis (session/token storage) |
| File Storage | AWS S3 (firearm images) |
| Containerisation | Docker |
| Deployment | Docker Compose behind Nginx |
@@ -23,12 +23,12 @@ The live site is available at **[dfguide.onixbyte.cn](https://dfguide.onixbyte.c
## Architecture
| Component | Tech Stack |
|---------------|---------------------------------------------------------------|
| **Frontend** | React 19, TypeScript, Tailwind CSS 4, Ant Design 6, React Router 7, Redux Toolkit, TanStack Virtual |
| **Backend** | Spring Boot 3, Java 21, PostgreSQL, MyBatis, Flyway, Redis |
| **Auth** | JWT (access + refresh tokens), CAPTCHA integration |
| **Storage** | AWS S3 for image uploads |
| Component | Tech Stack |
| ------------ | --------------------------------------------------------------------------------------------------- |
| **Frontend** | React 19, TypeScript, Tailwind CSS 4, Ant Design 6, React Router 7, Redux Toolkit, TanStack Virtual |
| **Backend** | Spring Boot 3, Java 21, PostgreSQL, MyBatis, Flyway, Redis |
| **Auth** | JWT (access + refresh tokens), CAPTCHA integration |
| **Storage** | AWS S3 for image uploads |
The frontend is a static site served by Vite, communicating with the Spring Boot REST API backend. Authentication uses JWT access and refresh tokens with Redis-backed refresh token management.
@@ -6,13 +6,13 @@ title: OnixByte Toolbox API
All modules are published under the `com.onixbyte` group ID. Each module has its own base package:
| Module | Maven Artifact | Base Package |
|----------------------|------------------------|---------------------------------------|
| Common Toolbox | `common-toolbox` | `com.onixbyte.common` |
| Crypto Toolbox | `crypto-toolbox` | `com.onixbyte.crypto` |
| Math Toolbox | `math-toolbox` | `com.onixbyte.math` |
| Tuple | `tuple` | `com.onixbyte.tuple` |
| Identity Generator | `identity-generator` | `com.onixbyte.identitygenerator` |
| Module | Maven Artifact | Base Package |
| ------------------ | -------------------- | -------------------------------- |
| Common Toolbox | `common-toolbox` | `com.onixbyte.common` |
| Crypto Toolbox | `crypto-toolbox` | `com.onixbyte.crypto` |
| Math Toolbox | `math-toolbox` | `com.onixbyte.math` |
| Tuple | `tuple` | `com.onixbyte.tuple` |
| Identity Generator | `identity-generator` | `com.onixbyte.identitygenerator` |
---
@@ -28,16 +28,16 @@ import com.onixbyte.common.adapter.ObjectMapAdapter;
### Utility Classes
| Class | Description |
|--------------------|----------------------------------------------------------|
| `AesUtil` | AES symmetric encryption/decryption with key generation |
| `Base64Util` | Base64 encoding and decoding with multiple charset support|
| `BoolUtil` | Boolean parsing and conversion utilities |
| `BranchUtil` | Conditional branching helpers with functional-style chains|
| `CollectionUtil` | Collection manipulation — grouping, partitioning, merging |
| `HashUtil` | Hashing utilities supporting MD5, SHA-1, SHA-256, SHA-512 |
| `MapUtil` | Map builder, merge, and transformation helpers |
| `RangeUtil` | Numeric range operations with boundary handling |
| Class | Description |
| ---------------- | ---------------------------------------------------------- |
| `AesUtil` | AES symmetric encryption/decryption with key generation |
| `Base64Util` | Base64 encoding and decoding with multiple charset support |
| `BoolUtil` | Boolean parsing and conversion utilities |
| `BranchUtil` | Conditional branching helpers with functional-style chains |
| `CollectionUtil` | Collection manipulation — grouping, partitioning, merging |
| `HashUtil` | Hashing utilities supporting MD5, SHA-1, SHA-256, SHA-512 |
| `MapUtil` | Map builder, merge, and transformation helpers |
| `RangeUtil` | Numeric range operations with boundary handling |
**AesUtil Example:**
@@ -70,12 +70,12 @@ Provides a clean abstraction for loading cryptographic keys in PEM format. Suppo
### Key Loaders
| Class | Description |
|---------------------------|--------------------------------------------|
| `RSAPrivateKeyLoader` | Load RSA private keys from PEM strings |
| `RSAPublicKeyLoader` | Load RSA public keys from PEM strings |
| `ECPrivateKeyLoader` | Load ECDSA private keys from PEM strings |
| `ECPublicKeyLoader` | Load ECDSA public keys from PEM strings |
| Class | Description |
| --------------------- | ---------------------------------------- |
| `RSAPrivateKeyLoader` | Load RSA private keys from PEM strings |
| `RSAPublicKeyLoader` | Load RSA public keys from PEM strings |
| `ECPrivateKeyLoader` | Load ECDSA private keys from PEM strings |
| `ECPublicKeyLoader` | Load ECDSA public keys from PEM strings |
All key loaders implement either `PrivateKeyLoader` or `PublicKeyLoader` interfaces.
@@ -99,9 +99,9 @@ var ecPublicKey = new ECPublicKeyLoader().load(pemString);
### Exceptions
| Class | Description |
|------------------------|---------------------------------------------------|
| `KeyLoadingException` | Thrown when a PEM-formatted key fails to parse |
| Class | Description |
| --------------------- | ---------------------------------------------- |
| `KeyLoadingException` | Thrown when a PEM-formatted key fails to parse |
---
@@ -111,10 +111,10 @@ Statistical computation utilities for working with numeric datasets.
### Core Classes
| Class | Description |
|-------------------------|----------------------------------------------------------|
| `Calculator` | Statistical calculator for mean, median, variance, standard deviation, sum, min, max |
| `PercentileCalculator` | Percentile computation with configurable interpolation strategies |
| Class | Description |
| ---------------------- | ------------------------------------------------------------------------------------ |
| `Calculator` | Statistical calculator for mean, median, variance, standard deviation, sum, min, max |
| `PercentileCalculator` | Percentile computation with configurable interpolation strategies |
**Calculator Example:**
@@ -135,9 +135,9 @@ double p99 = calculator.calculate(99);
### Model
| Class | Description |
|-------------------|----------------------------------------------------------------|
| `QuartileBounds` | Holds Q1, median (Q2), Q3 values along with IQR and whisker bounds |
| Class | Description |
| ---------------- | ------------------------------------------------------------------ |
| `QuartileBounds` | Holds Q1, median (Q2), Q3 values along with IQR and whisker bounds |
---
@@ -147,12 +147,12 @@ Lightweight generic tuple types for when you need to return multiple values with
### Classes
| Class | Type Parameters | Mutability |
|--------------------|-----------------|------------|
| `Tuple<A, B>` | Two elements | Mutable |
| `ImmutableTuple<A, B>` | Two elements | Immutable |
| `Triple<A, B, C>` | Three elements | Mutable |
| `ImmutableTriple<A, B, C>` | Three elements | Immutable |
| Class | Type Parameters | Mutability |
| -------------------------- | --------------- | ---------- |
| `Tuple<A, B>` | Two elements | Mutable |
| `ImmutableTuple<A, B>` | Two elements | Immutable |
| `Triple<A, B, C>` | Three elements | Mutable |
| `ImmutableTriple<A, B, C>` | Three elements | Immutable |
**Example:**
@@ -183,10 +183,10 @@ Generates unique identifiers suitable for use as database primary keys or distri
### Implementations
| Class | Description |
|------------------------------|-----------------------------------------------------------------|
| Class | Description |
| ---------------------------- | ------------------------------------------------------------------- |
| `SequentialUuidGenerator` | Generates time-ordered, sequential UUIDs (optimised for DB indexes) |
| `SnowflakeIdentityGenerator` | Snowflake-style distributed unique ID generation |
| `SnowflakeIdentityGenerator` | Snowflake-style distributed unique ID generation |
**Sequential UUID:**
@@ -204,6 +204,6 @@ long id = generator.nextId(); // 64-bit snowflake ID
### Exceptions
| Class | Description |
|-------------------|----------------------------------------------------------------|
| Class | Description |
| ----------------- | ------------------------------------------------------------------------ |
| `TimingException` | Thrown when the system clock moves backwards, compromising ID uniqueness |
@@ -13,7 +13,7 @@ The toolkit is available on Maven Central under the `com.onixbyte` group ID. Eac
## Modules
| Module | Artifact ID | Description |
|--------------------|----------------------|---------------------------------------------------------------------------|
| ------------------ | -------------------- | ------------------------------------------------------------------------- |
| Common Toolbox | `common-toolbox` | Everyday utilities — AES, hashing, Base64, collections, branching, ranges |
| Crypto Toolbox | `crypto-toolbox` | Public/private key loading for RSA and ECDSA algorithms |
| Math Toolbox | `math-toolbox` | Statistical calculation, percentile analysis, quartile computation |
@@ -21,12 +21,12 @@ The library models every ISO 3166-1 country and territory as an enum constant, g
Each region exposes four attributes:
| Attribute | Type | Description | Example |
|----------------|--------|---------------------------------|------------------------------------|
| `abbreviation` | String | ISO 3166-1 alpha-2 abbreviation | `HK`, `US`, `GB`, `RU` |
| `code` | String | ISO 3166-1 alpha-3 code | `HKG`, `USA`, `GBR`, `RUS` |
| Attribute | Type | Description | Example |
| -------------- | ------ | ----------------------------------- | ---------------------------------- |
| `abbreviation` | String | ISO 3166-1 alpha-2 abbreviation | `HK`, `US`, `GB`, `RU` |
| `code` | String | ISO 3166-1 alpha-3 code | `HKG`, `USA`, `GBR`, `RUS` |
| `callingCode` | String | E.164 international dialling prefix | `852`, `1`, `44`, `7` |
| `locale` | String | Default language and region tag | `zh_HK`, `en_US`, `en_GB`, `ru_RU` |
| `locale` | String | Default language and region tag | `zh_HK`, `en_US`, `en_GB`, `ru_RU` |
## Installation
@@ -20,16 +20,8 @@ This plugin detects the situation at startup and prints a clear, colour-coded wa
## Installation
<Tabs>
<Tab label="npm">
```bash
npm install vite-plugin-port-checker -D
```
</Tab>
<Tab label="pnpm">
```bash
pnpm add vite-plugin-port-checker -D
```
</Tab>
<Tab label="npm">```bash npm install vite-plugin-port-checker -D ```</Tab>
<Tab label="pnpm">```bash pnpm add vite-plugin-port-checker -D ```</Tab>
</Tabs>
## Usage