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
45 files changed
+194 -229

No files matched your search

+20 -25
View File
@@ -49,8 +49,8 @@ Minimal setup:
```tsx
// theme/index.tsx
import './index.css'; // optional
export * from '@rspress/core/theme-original';
import "./index.css" // optional
export * from "@rspress/core/theme-original"
```
**Critical import rule**: Inside `theme/` files, always import from `@rspress/core/theme-original`. The path `@rspress/core/theme` resolves to your own `theme/index.tsx`, which causes circular imports. (In `docs/` MDX files, `@rspress/core/theme` is fine — it correctly points to your custom theme.)
@@ -80,8 +80,8 @@ Override CSS custom properties for brand colors, backgrounds, text, code blocks,
```ts
// rspress.config.ts
export default defineConfig({
globalStyles: path.join(__dirname, 'styles/custom.css'),
});
globalStyles: path.join(__dirname, "styles/custom.css"),
})
```
> **Full variable list**: Read `references/css-variables.md` for all available CSS variables with light/dark defaults.
@@ -104,13 +104,11 @@ Inject content at specific positions in the layout without replacing built-in co
```tsx
// theme/index.tsx
import { Layout as OriginalLayout } from '@rspress/core/theme-original';
export * from '@rspress/core/theme-original';
import { Layout as OriginalLayout } from "@rspress/core/theme-original"
export * from "@rspress/core/theme-original"
export function Layout() {
return (
<OriginalLayout beforeNavTitle={<MyLogo />} bottom={<CustomFooter />} />
);
return <OriginalLayout beforeNavTitle={<MyLogo />} bottom={<CustomFooter />} />
}
```
@@ -132,8 +130,8 @@ rspress eject DocFooter # eject to theme/components/DocFooter/
Then re-export in `theme/index.tsx` (named export takes precedence over the wildcard):
```tsx
export * from '@rspress/core/theme-original';
export { DocFooter } from './components/DocFooter';
export * from "@rspress/core/theme-original"
export { DocFooter } from "./components/DocFooter"
```
> **Component list & patterns**: Read `references/eject-components.md` for available components, workflow, and common patterns.
@@ -147,38 +145,38 @@ Rspress has 27 built-in icons used across the UI. You can replace any of them by
**Icon type**: Each icon is a React component or a URL string:
```ts
import type { FC, SVGProps } from 'react';
type Icon = FC<SVGProps<SVGSVGElement>> | string;
import type { FC, SVGProps } from "react"
type Icon = FC<SVGProps<SVGSVGElement>> | string
```
**Example 1** — Replace an icon with a custom SVG component:
```tsx
// theme/index.tsx
export * from '@rspress/core/theme-original';
export * from "@rspress/core/theme-original"
// Named export overrides the wildcard — replaces the GitHub icon site-wide
export const IconGithub = (props: React.SVGProps<SVGSVGElement>) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...props}>
<path d="M12 2C6.477 2 2 6.484 2 12.017c0 ..." fill="currentColor" />
</svg>
);
)
```
**Example 2** — Use an SVGR import:
```tsx
// theme/index.tsx
export * from '@rspress/core/theme-original';
export * from "@rspress/core/theme-original"
import CustomGithubIcon from './icons/github.svg?react';
export const IconGithub = CustomGithubIcon;
import CustomGithubIcon from "./icons/github.svg?react"
export const IconGithub = CustomGithubIcon
```
**Using `SvgWrapper` in MDX or custom components**:
```mdx
import { SvgWrapper, IconGithub } from '@rspress/core/theme';
import { SvgWrapper, IconGithub } from "@rspress/core/theme"
<SvgWrapper icon={IconGithub} width={24} height={24} />
```
@@ -197,13 +195,10 @@ For components that should render on every page without theme overrides:
// rspress.config.ts
export default defineConfig({
globalUIComponents: [
path.join(__dirname, 'components', 'BackToTop.tsx'),
[
path.join(__dirname, 'components', 'Analytics.tsx'),
{ trackingId: '...' },
path.join(__dirname, "components", "BackToTop.tsx"),
[path.join(__dirname, "components", "Analytics.tsx"), { trackingId: "..." }],
],
],
});
})
```
---
@@ -50,8 +50,8 @@ Ejected source is placed in `theme/components/<ComponentName>/`.
```tsx
// theme/index.tsx
export * from '@rspress/core/theme-original';
export { DocFooter } from './components/DocFooter';
export * from "@rspress/core/theme-original"
export { DocFooter } from "./components/DocFooter"
```
The named export takes precedence over the wildcard re-export, so Rspress uses your custom version.
@@ -64,21 +64,21 @@ The most common eject use case is wrapping the entire app in a context provider
```tsx
// theme/components/Root/index.tsx
import type { RootProps } from '@rspress/core/theme';
import type { RootProps } from "@rspress/core/theme"
export function Root({ children }: RootProps) {
return (
<ThemeProvider>
<AnalyticsProvider>{children}</AnalyticsProvider>
</ThemeProvider>
);
)
}
```
```tsx
// theme/index.tsx
export * from '@rspress/core/theme-original';
export { Root } from './components/Root';
export * from "@rspress/core/theme-original"
export { Root } from "./components/Root"
```
## Common Pattern: Custom Home Page (HomeLayout)
@@ -87,12 +87,12 @@ When the default home page structure (Hero + Features) doesn't meet the design r
```tsx
// theme/components/HomeLayout/index.tsx
import { useSite, useLang } from '@rspress/core/runtime';
import { useSite, useLang } from "@rspress/core/runtime"
export function HomeLayout() {
const site = useSite();
const lang = useLang();
const { title, description } = site.siteData;
const site = useSite()
const lang = useLang()
const { title, description } = site.siteData
return (
<div className="custom-home">
@@ -100,10 +100,7 @@ export function HomeLayout() {
<h1>{title}</h1>
<p>{description}</p>
<div className="hero-actions">
<a
href={lang === 'zh' ? '/zh/guide/start' : '/guide/start'}
className="primary-btn"
>
<a href={lang === "zh" ? "/zh/guide/start" : "/guide/start"} className="primary-btn">
Get Started
</a>
<a href="https://github.com/..." className="secondary-btn">
@@ -116,14 +113,14 @@ export function HomeLayout() {
{/* Custom content: testimonials, stats, demos, etc. */}
</section>
</div>
);
)
}
```
```tsx
// theme/index.tsx
export * from '@rspress/core/theme-original';
export { HomeLayout } from './components/HomeLayout';
export * from "@rspress/core/theme-original"
export { HomeLayout } from "./components/HomeLayout"
```
The named export overrides the built-in `HomeLayout` from the wildcard re-export — no need to eject first.
@@ -134,16 +131,16 @@ If you only need to add content before/after the Hero or Features sections (with
```tsx
// theme/components/DocFooter/index.tsx
import { useFrontmatter } from '@rspress/core/runtime';
import { useFrontmatter } from "@rspress/core/runtime"
export function DocFooter() {
const frontmatter = useFrontmatter();
const frontmatter = useFrontmatter()
return (
<footer className="custom-doc-footer">
{frontmatter.author && <span>Author: {frontmatter.author}</span>}
<a href="https://github.com/...">Edit this page</a>
</footer>
);
)
}
```
@@ -71,11 +71,11 @@ All examples below follow the same structure in `theme/index.tsx`. The key parts
```tsx
// theme/index.tsx
import { Layout as OriginalLayout } from '@rspress/core/theme-original';
export * from '@rspress/core/theme-original';
import { Layout as OriginalLayout } from "@rspress/core/theme-original"
export * from "@rspress/core/theme-original"
export function Layout() {
return <OriginalLayout beforeNavTitle={<MyLogo />} />;
return <OriginalLayout beforeNavTitle={<MyLogo />} />
}
```
@@ -83,8 +83,8 @@ export function Layout() {
```tsx
// theme/index.tsx
import { Layout as OriginalLayout } from '@rspress/core/theme-original';
export * from '@rspress/core/theme-original';
import { Layout as OriginalLayout } from "@rspress/core/theme-original"
export * from "@rspress/core/theme-original"
export function Layout() {
return (
@@ -93,7 +93,7 @@ export function Layout() {
bottom={<footer>© 2025 My Company</footer>}
afterOutline={<div>Related resources</div>}
/>
);
)
}
```
@@ -101,17 +101,17 @@ export function Layout() {
```tsx
// theme/index.tsx
import { Layout as OriginalLayout } from '@rspress/core/theme-original';
import { useLang } from '@rspress/core/runtime';
export * from '@rspress/core/theme-original';
import { Layout as OriginalLayout } from "@rspress/core/theme-original"
import { useLang } from "@rspress/core/runtime"
export * from "@rspress/core/theme-original"
function LocalizedBanner() {
const lang = useLang();
return <div>{lang === 'zh' ? '欢迎' : 'Welcome'}</div>;
const lang = useLang()
return <div>{lang === "zh" ? "欢迎" : "Welcome"}</div>
}
export function Layout() {
return <OriginalLayout top={<LocalizedBanner />} />;
return <OriginalLayout top={<LocalizedBanner />} />
}
```
@@ -121,17 +121,15 @@ The `components` slot accepts a `Record<string, React.ComponentType>` to overrid
```tsx
// theme/index.tsx
import { Layout as OriginalLayout } from '@rspress/core/theme-original';
export * from '@rspress/core/theme-original';
import { Layout as OriginalLayout } from "@rspress/core/theme-original"
export * from "@rspress/core/theme-original"
function CustomH1({ children }: { children: React.ReactNode }) {
return (
<h1 style={{ borderBottom: '2px solid var(--rp-c-brand)' }}>{children}</h1>
);
return <h1 style={{ borderBottom: "2px solid var(--rp-c-brand)" }}>{children}</h1>
}
export function Layout() {
return <OriginalLayout components={{ h1: CustomH1 }} />;
return <OriginalLayout components={{ h1: CustomH1 }} />
}
```
+1 -1
View File
@@ -5,7 +5,7 @@ This project incorporates the following third-party open source software.
## Direct Dependencies
| Package | License |
|-------------------|---------|
| ----------------- | ------- |
| @rspress/core | MIT |
| react | MIT |
| react-dom | MIT |
+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" }
}
}
```
+2 -2
View File
@@ -20,10 +20,10 @@ sound more confident and professional.
## Scenario Cheatsheet
| 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.
@@ -11,7 +11,7 @@ author:
---
| 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 |
@@ -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)`?
@@ -276,6 +277,6 @@ 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` |
@@ -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`).
+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">
+11 -11
View File
@@ -7,7 +7,7 @@ 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 |
@@ -46,11 +46,11 @@ 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 |
| `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 |
@@ -83,7 +83,7 @@ DefaultTextProducer textProducer = DefaultTextProducer.builder()
```
| Method | Default Value | Description |
|----------|-----------------------------------------------------------|--------------------------------|
| -------- | ----------------------------------- | ------------------------------ |
| `length` | `6` | Length of generated text |
| `chars` | `a-z`, `A-Z`, `0-9` (62 characters) | Characters used for generation |
@@ -112,10 +112,10 @@ DefaultWordRenderer wordRenderer = DefaultWordRenderer.builder()
```
| Method | Default Value | Description |
|-------------|-----------------------------------|-----------------------------------------|
| ------------ | ---------------------- | -------------------------------------- |
| `fontSize` | `40` | Font size in pixels |
| `fonts` | `["Arial", "Courier"]` | Font families to use (randomly chosen) |
| `fontColour`| `Color.BLACK` | Font colour |
| `fontColour` | `Color.BLACK` | Font colour |
| `charSpace` | `2` | Space between characters in pixels |
| `fontStyle` | `FontStyle.BOLD` | Font style to apply |
@@ -124,7 +124,7 @@ DefaultWordRenderer wordRenderer = DefaultWordRenderer.builder()
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 |
@@ -153,7 +153,7 @@ WaterRipple gimpy = WaterRipple.builder()
```
| Method | Default Value | Description |
|-----------------|---------------------------------------------|------------------------------|
| --------------- | ---------------------------------------- | ------------------------- |
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | The noise producer to use |
### FishEyeGimpy
@@ -176,7 +176,7 @@ ShadowGimpy gimpy = ShadowGimpy.builder()
```
| Method | Default Value | Description |
|-----------------|---------------------------------------------|------------------------------|
| --------------- | ---------------------------------------- | ------------------------- |
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | The noise producer to use |
---
@@ -205,7 +205,7 @@ DefaultNoiseProducer noise = DefaultNoiseProducer.builder()
```
| 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
@@ -110,7 +111,7 @@ 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 |
@@ -159,7 +160,7 @@ 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 `[]`) |
@@ -167,7 +168,7 @@ your-marketplace-repo/
**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 |
@@ -203,7 +204,7 @@ 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 |
@@ -7,7 +7,7 @@ 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 |
@@ -22,7 +22,7 @@ The backend is a Spring Boot 3 application organised under the base package `com
### 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 |
@@ -30,7 +30,7 @@ The backend is a Spring Boot 3 application organised under the base package `com
### 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 |
@@ -40,7 +40,7 @@ The backend is a Spring Boot 3 application organised under the base package `com
### Modifications
| 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 |
@@ -52,18 +52,18 @@ The backend is a Spring Boot 3 application organised under the base package `com
### 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 |
| `/mod-codes` | Hero Layout | Modification Codes | Modification code library |
| `/legal` | Hero Layout | Legal | Legal and privacy information |
| `/login` | Empty Layout| Login | User authentication page |
| `/login` | Empty Layout | Login | User authentication page |
## Frontend State Management
@@ -83,7 +83,7 @@ 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) |
@@ -24,7 +24,7 @@ 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 |
@@ -7,7 +7,7 @@ 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` |
@@ -29,11 +29,11 @@ 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|
| `Base64Util` | Base64 encoding and decoding with multiple charset support |
| `BoolUtil` | Boolean parsing and conversion utilities |
| `BranchUtil` | Conditional branching helpers with functional-style chains|
| `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 |
@@ -71,7 +71,7 @@ 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 |
@@ -100,7 +100,7 @@ var ecPublicKey = new ECPublicKeyLoader().load(pemString);
### Exceptions
| Class | Description |
|------------------------|---------------------------------------------------|
| --------------------- | ---------------------------------------------- |
| `KeyLoadingException` | Thrown when a PEM-formatted key fails to parse |
---
@@ -112,7 +112,7 @@ 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 |
@@ -136,7 +136,7 @@ double p99 = calculator.calculate(99);
### Model
| Class | Description |
|-------------------|----------------------------------------------------------------|
| ---------------- | ------------------------------------------------------------------ |
| `QuartileBounds` | Holds Q1, median (Q2), Q3 values along with IQR and whisker bounds |
---
@@ -148,7 +148,7 @@ 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 |
@@ -184,7 +184,7 @@ Generates unique identifiers suitable for use as database primary keys or distri
### Implementations
| Class | Description |
|------------------------------|-----------------------------------------------------------------|
| ---------------------------- | ------------------------------------------------------------------- |
| `SequentialUuidGenerator` | Generates time-ordered, sequential UUIDs (optimised for DB indexes) |
| `SnowflakeIdentityGenerator` | Snowflake-style distributed unique ID generation |
@@ -205,5 +205,5 @@ long id = generator.nextId(); // 64-bit snowflake ID
### Exceptions
| 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 |
@@ -22,7 +22,7 @@ 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` |
| `callingCode` | String | E.164 international dialling prefix | `852`, `1`, `44`, `7` |
@@ -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
@@ -11,7 +11,7 @@ author:
## 调料投放时机
| 调料类型 | 放调料时机 | 适用菜品 | 作用 |
|--------------|----------|----------------|---------------------|
| -------------------- | ---------------- | ---------------------------- | -------------------------------------- |
| **盐** | 最后放 | 菜叶子 | 防止菜叶变软出水,保证口感干爽脆嫩 |
| | 中间放 | 土豆丝、豆角、蒜苔等 | 更好入味 |
| **味精、生抽、蚝油** | 偏后放 | 各类需要增鲜提香的菜品 | 增鲜提香,避免高温破坏鲜味和香味 |
@@ -24,7 +24,7 @@ author:
## 快速参考
| 调料 | 投放时机 | 作用 | 示例 |
|-----------------|----------------|------------------------|------------------------|
| ----------------------- | ------------------- | -------------------------------------------- | ------------------------------------- |
| **盐** | 出锅前 10 - 15 秒放 | 避免提前放盐导致菜叶出水、变软,保持脆嫩口感 | 炒生菜、菠菜时,关火前撒盐翻炒均匀 |
| **蒜末 / 姜末** | 热油后先放 | 爆香提味,激发香味 | 油热后下蒜末炝锅,再放青菜翻炒 |
| **生抽 / 蚝油**(可选) | 盐之后放 | 增鲜提味,少量即可,避免盖过蔬菜原味 | 炒上海青时,加盐后滴 1 - 2 滴生抽翻炒 |
@@ -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" }
}
}
```
+1 -1
View File
@@ -18,7 +18,7 @@ author:
## 场景速查表
| 场景 | ❌ 别用(听起来……) | ✅ 改用(听起来……) | 为什么有效 |
|----------|--------------------------------------------------------------|----------------------------------------------------------|-----------------------------------------------|
| ---------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| 回复晚了 | **Sorry for the delay**<br/>(抱歉回复晚了) | **Thanks for your patience**<br/>(感谢你的耐心等待) | 前者在道歉,后者在感谢——从「我做错了」转变为「你太好了」,既表达了歉意又让对方感到被尊重 |
| 约时间 | **What works best for you?**<br/>(你什么时候方便?) | **Could you do …?**<br/>(你可以在某某时间吗?) | 前者把决定权完全推给对方,后者主动给出选项,减少来回沟通的成本 |
| 帮助了别人之后 | **No problem / No worries**<br/>(没问题 / 别担心) | **Always happy to help**<br/>(乐于效劳) | 前者暗示这件事"本来可能是个问题",后者传递出你乐在其中、下次还愿意帮 |
@@ -21,6 +21,6 @@ tags:
于是对于 PowerNap 这个功能来说,我们只能从命令行下手,首先使用 **`pmset -g`** 命令查看当前状态,找到 **`powernap`** 的值,如果不是 0 ,说明是启用的状态,使用命令 **`sudo pmset -a powernap 0`** 关掉它。
同时,还有另外一个 **`tcpkeepalive`** ,这个默认应该也不是 0 ,也要关掉,它决定了你的 rmbp 在休眠时是否要保持 tcp 连接。 **`sudo pmset -a tcpkeepalive 0`** ,执行这条命令会导致终端提示:***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.***
同时,还有另外一个 **`tcpkeepalive`** ,这个默认应该也不是 0 ,也要关掉,它决定了你的 rmbp 在休眠时是否要保持 tcp 连接。 **`sudo pmset -a tcpkeepalive 0`** ,执行这条命令会导致终端提示:**_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._**
大概是说关了的话某些功能会受到限制,其实就是系统功能不能休眠时联网了,我相信真有人偷了你 Mac,它也连不上网的。
@@ -11,7 +11,7 @@ author:
---
| 中文字号 | 英文字号(磅)/pt | 毫米/mm | 像素/px |
|------|------------|-------|-------|
| -------- | ----------------- | ------- | ------- |
| 初号 | 42 | 14.82 | 56 |
| 小初 | 36 | 12.7 | 48 |
| 一号 | 26 | 9.17 | 34.7 |
@@ -68,7 +68,7 @@ createRoot(document.getElementById("root")!).render(
<StyleProvider>
<ConfigProvider>
<App>
<RouterProvider/>
<RouterProvider />
</App>
</ConfigProvider>
</StyleProvider>
@@ -100,7 +100,7 @@ N+1 问题是指 JPA 先执行 1 条查询获取父实体,再为每条父实
**修复方案:**
| 方式 | 适用场景 |
|---------------------------|----------------------|
| ---------------------------- | ---------------------------------- |
| `@EntityGraph` | 声明式,适合为特定实体定制抓取计划 |
| `@Query` 中使用 `JOIN FETCH` | 按查询精细控制 |
| `@BatchSize` | 将 N+1 降低为 N/k+1,批量加载 |
@@ -139,6 +139,7 @@ post.setAuthor(userRepository.getReferenceById(userId));
@Query("SELECT new com.example.UserDto(u.id, u.name) FROM User u WHERE u.id = :id")
UserDto findUserDtoById(@Param("id") long id);
```
3. **在 Service 方法上使用 `@Transactional(readOnly = true)`** — 使 Session 在整个方法作用域内保持打开。
### 什么时候该用 `@Transactional(readOnly = true)`?
@@ -271,6 +272,6 @@ public class Product {
### 如何选择
| 场景 | 注解 |
|----------------------------------------|--------------------|
| -------------------------------------- | ---------------- |
| 平铺字段固定的嵌套对象(如地址、配置) | `@JsonUnwrapped` |
| 平铺 key 不固定的动态键值对 | `@JsonAnyGetter` |
@@ -119,7 +119,7 @@ author:
- 数据操作约定:
- 对于简单数据库操作,使用 JPA。
- 对于复杂数据库操作,使用 MyBatis。
- 当进行分页查询时,页码应从 0 开始(*兼容 Spring Data JPA*)。
- 当进行分页查询时,页码应从 0 开始(_兼容 Spring Data JPA_)。
- **数据操作方法命名约定**:
- 对于**查询数据列表**:方法**必须**以 `selectListBy` 开头,紧随其后是筛选条件(例如,`selectListByUserId`、`selectListByDepartmentIdAndStatus`)。这些方法也必须包含一个 `PageRequest` 参数用于分页。
- 对于查询**单个数据记录**:方法**必须**以 `selectOne` 开头(例如,`selectOneById`、`selectOneByUsername`)。
+6 -7
View File
@@ -25,11 +25,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
@@ -53,7 +53,7 @@ echo -n "user@example.com" | tr '[:upper:]' '[:lower:]' | sha256sum | cut -d ' '
`/avatar/` 端点接受以下查询参数来定制结果:
| 参数 | 描述 | 示例 |
|-----|------------------------|----------------|
| ---- | ------------------------------- | -------------- |
| `s` | 图片尺寸(像素,默认 80) | `?s=200` |
| `d` | 未找到 Gravatar 时的默认图片 | `?d=identicon` |
| `r` | 内容分级(`g`、`pg`、`r`、`x`) | `?r=g` |
@@ -76,8 +76,7 @@ echo -n "user@example.com" | tr '[:upper:]' '[:lower:]' | sha256sum | cut -d ' '
src="https://gravatar.com/avatar/a3b4c5d6e7f8?s=160&d=robohash&r=g"
alt="用户头像"
width="160"
height="160"
/>
height="160" />
```
始终传入 `d` 参数以避免未设置 Gravatar 的用户出现裂图。`identicon` 和 `robohash` 是常用的选择,因为它们能为每个哈希值生成唯一且易于辨识的图片。
@@ -7,7 +7,7 @@ title: Calendar Toolbox API
库的代码组织在基础包 `com.onixbyte.calendar` 下,结构如下:
| 包 | 描述 |
|---|---|
| ------------------------------------------ | ---------------------------------- |
| `com.onixbyte.calendar` | 根日历对象 |
| `com.onixbyte.calendar.component` | iCalendar 组件(VEVENT、VTODO 等) |
| `com.onixbyte.calendar.component.property` | 组件级属性 |
@@ -47,7 +47,7 @@ String icsContent = calendar.formatted();
所有日历级属性位于 `com.onixbyte.calendar.property`,实现 `CalendarProperty` 接口。
| 类 | iCalendar 属性 | 描述 |
|---|---|---|
| ------------------------ | -------------------- | --------------------------------------- |
| `CalendarScale` | `CALSCALE` | 日历系统(例如 GREGORIAN) |
| `Method` | `METHOD` | iCalendar 方法(例如 PUBLISH、REQUEST) |
| `ProductIdentifier` | `PRODID` | 日历的产品标识符 |
@@ -277,7 +277,7 @@ Alarm emailAlarm = Alarm.builder()
组件属性位于 `com.onixbyte.calendar.component.property`,实现 `ComponentProperty` 接口。
| 类 | iCalendar 属性 | 描述 |
|---|---|---|
| ------------------------- | ------------------ | ---------------------------------------------- |
| `Action` | `ACTION` | 闹钟操作类型(AUDIO、DISPLAY、EMAIL) |
| `Attachment` | `ATTACH` | 文档附件 |
| `Attendee` | `ATTENDEE` | 事件/任务参与者 |
@@ -328,7 +328,7 @@ Alarm emailAlarm = Alarm.builder()
参数位于 `com.onixbyte.calendar.parameter`,为组件属性提供额外限定。
| 类 | iCalendar 参数 | 描述 |
|---|---|---|
| ----------------------------- | ---------------- | ---------------------------------------------- |
| `AlarmTriggerRelationship` | `RELATED` | 触发器关联(START、END) |
| `AlternateTextRepresentation` | `ALTREP` | 替代文本 URI |
| `CalendarUserType` | `CUTYPE` | 日历用户类型(INDIVIDUAL、GROUP、RESOURCE 等) |
@@ -357,7 +357,7 @@ Alarm emailAlarm = Alarm.builder()
位于 `com.onixbyte.calendar.recurrence`。
| 类 | 描述 |
|---|---|
| ------------ | ------------------------------------------------------------ |
| `Frequency` | 重复频率常量(DAILY、WEEKLY、MONTHLY、YEARLY),用于重复规则 |
| `WeekdayNum` | 重复规则的星期序号(例如第 2 个星期一) |
@@ -368,7 +368,7 @@ Alarm emailAlarm = Alarm.builder()
位于 `com.onixbyte.calendar.value`。
| 类 | 描述 |
|---|---|
| ------------------- | ------------------------------------- |
| `FreeBusyTimeValue` | 表示空闲/忙碌时间值 |
| `PeriodOfTime` | 表示一个时间段,包含开始和结束 |
| `PropertyValue` | 属性的基础值类型 |
@@ -22,10 +22,8 @@ Calendar Toolbox 是一个 Java 库,旨在简化遵循 iCalendar 规范(RFC
<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">
@@ -7,7 +7,7 @@ title: Captcha API
库的代码组织在基础包 `com.onixbyte.captcha` 下,结构如下:
| 包 | 描述 |
|---|---|
| -------------------------------------- | ---------------------- |
| `com.onixbyte.captcha` | 核心接口 |
| `com.onixbyte.captcha.impl` | 默认实现 |
| `com.onixbyte.captcha.text` | 文本生成器和渲染器接口 |
@@ -46,7 +46,7 @@ BufferedImage image = captcha.createImage(text);
### DefaultCaptchaProducer Builder
| 方法 | 默认值 | 描述 |
|---|---|---|
| -------------------- | --------------------------------------------- | -------------- |
| `textProducer` | `DefaultTextProducer.builder().build()` | 文本生成器 |
| `wordRenderer` | `DefaultWordRenderer.builder().build()` | 文字渲染器 |
| `gimpyEngine` | `WaterRipple.builder().build()` | 扭曲引擎 |
@@ -83,7 +83,7 @@ DefaultTextProducer textProducer = DefaultTextProducer.builder()
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| -------- | ----------------------------------- | -------------------- |
| `length` | `6` | 生成文本的长度 |
| `chars` | `a-z`、`A-Z`、`0-9`(共 62 个字符) | 生成文本使用的字符集 |
@@ -112,7 +112,7 @@ DefaultWordRenderer wordRenderer = DefaultWordRenderer.builder()
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| ------------ | ---------------------- | ------------------ |
| `fontSize` | `40` | 字号(像素) |
| `fonts` | `["Arial", "Courier"]` | 字体族(随机选择) |
| `fontColour` | `Color.BLACK` | 字体颜色 |
@@ -124,7 +124,7 @@ DefaultWordRenderer wordRenderer = DefaultWordRenderer.builder()
定义 CAPTCHA 文字渲染支持的字体样式。
| 值 | 对应的 AWT 常量 | 描述 |
|---|---|---|
| ------------- | ---------------------- | ------------ | ------ |
| `PLAIN` | `java.awt.Font.PLAIN` | 普通样式 |
| `BOLD` | `java.awt.Font.BOLD` | 粗体 |
| `ITALIC` | `java.awt.Font.ITALIC` | 斜体 |
@@ -153,7 +153,7 @@ WaterRipple gimpy = WaterRipple.builder()
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| --------------- | ---------------------------------------- | ---------- |
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | 噪点生成器 |
### FishEyeGimpy
@@ -176,7 +176,7 @@ ShadowGimpy gimpy = ShadowGimpy.builder()
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| --------------- | ---------------------------------------- | ---------- |
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | 噪点生成器 |
---
@@ -205,7 +205,7 @@ DefaultNoiseProducer noise = DefaultNoiseProducer.builder()
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| ------------- | ------------- | -------- |
| `noiseColour` | `Color.BLACK` | 噪点颜色 |
#### NoNoiseProducer
@@ -243,6 +243,6 @@ DefaultBackgroundProducer background = DefaultBackgroundProducer.builder()
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| ------------ | ------------------ | ------------ |
| `colourFrom` | `Color.LIGHT_GRAY` | 渐变起始颜色 |
| `colourTo` | `Color.WHITE` | 渐变结束颜色 |
@@ -23,10 +23,7 @@ Captcha 是一个用于生成 CAPTCHA 验证码图片的 Java 库。本项目是
<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 会被直接部署到 Claude Code 自身的 Skills 目录(`~/.claude/sk
| Windows (amd64) | `ccsm-windows-amd64.exe` |
将二进制文件放到 `PATH` 中的某个目录,并重命名为 `ccsm`(Windows 上为 `ccsm.exe`)。
</Tab>
<Tab label="Cargo 安装">
```bash
@@ -110,7 +111,7 @@ ccsm marketplace remove my-marketplace
CCSM 支持两种部署模式:
| 模式 | 行为 | 适用场景 |
|------|------|----------|
| -------------- | ------------------------------------------- | ------------------------------------- |
| `copy`(默认) | 将文件物理复制到 `~/.claude/skills/<name>/` | 日常使用 — 安全且自包含 |
| `link` | 创建指向本地存储的符号链接 | Skill 开发 — 对源文件的修改会立即生效 |
@@ -159,7 +160,7 @@ your-marketplace-repo/
**顶层字段:**
| 字段 | 必需 | 说明 |
|------|------|------|
| --------- | ---- | ----------------------------- |
| `name` | 是 | Marketplace 的显示名称 |
| `version` | 否 | 用于自行追踪的任意版本号 |
| `skills` | 否 | Skill 条目数组(默认为 `[]`) |
@@ -167,7 +168,7 @@ your-marketplace-repo/
**Skill 条目字段:**
| 字段 | 必需 | 说明 |
|------|------|------|
| ------------- | ---- | ----------------------------------------------------------- |
| `name` | 是 | Skill 的唯一标识符(用于 `ccsm install <name>`) |
| `description` | 是 | 在 `ccsm search` 输出中显示的一行摘要 |
| `repository` | 是 | Skill 的公开 Git 仓库 URL |
@@ -203,7 +204,7 @@ my-skill-repo/
## 数据存储位置
| 路径 | 用途 |
|------|------|
| ------------------------------ | ----------------------------------------------- |
| `~/.claude/skills/` | Claude Code 的 Skills 目录 —— Skills 的部署目标 |
| `~/.config/ccsm/config.json` | CCSM 配置文件(已注册的 Marketplace、默认模式) |
| `~/.config/ccsm/marketplaces/` | 缓存的 Marketplace 清单 |
@@ -7,7 +7,7 @@ title: Delta Force Guide API
后端是基于 Spring Boot 3 的应用程序,代码组织在基础包 `com.onixbyte.deltaforceguide` 下:
| 包 | 描述 |
|---|---|
| ------------- | --------------------------- |
| `controller` | REST API 端点控制器 |
| `service` | 业务逻辑层 |
| `repository` | MyBatis 数据访问层 |
@@ -22,7 +22,7 @@ title: Delta Force Guide API
### 认证
| 方法 | 路径 | 描述 | 认证 |
|---|---|---|---|
| ------ | ------------------- | ----------------- | ---- |
| `POST` | `/api/auth/login` | 使用凭证登录 | 否 |
| `POST` | `/api/auth/refresh` | 刷新 access token | 否 |
| `GET` | `/api/auth/profile` | 获取当前用户信息 | 是 |
@@ -30,7 +30,7 @@ title: Delta Force Guide API
### 枪械
| 方法 | 路径 | 描述 |
|---|---|---|
| -------- | ------------------- | ------------------------------ |
| `GET` | `/api/firearms` | 枪械列表(分页,可按类型筛选) |
| `GET` | `/api/firearms/:id` | 按 ID 获取枪械详情 |
| `POST` | `/api/firearms` | 创建新枪械 |
@@ -40,7 +40,7 @@ title: Delta Force Guide API
### 改装
| 方法 | 路径 | 描述 |
|---|---|---|
| -------- | --------------------------------- | ------------------------------------ |
| `GET` | `/api/modifications` | 改装列表(分页,可按枪械和标签筛选) |
| `GET` | `/api/modifications/:id` | 按 ID 获取改装详情 |
| `POST` | `/api/modifications` | 创建改装 |
@@ -52,13 +52,13 @@ title: Delta Force Guide API
### 标签
| 方法 | 路径 | 描述 |
|---|---|---|
| ----- | ----------- | ------------ |
| `GET` | `/api/tags` | 获取所有标签 |
## 前端路由
| 路径 | 布局 | 页面 | 描述 |
|---|---|---|---|
| ------------ | -------- | -------- | --------------- |
| `/` | 主布局 | 枪械浏览 | 首页 — 枪械列表 |
| `/firearms` | 主布局 | 枪械浏览 | 枪械详情与搜索 |
| `/mod-codes` | 主布局 | 改装代码 | 改装代码库 |
@@ -83,7 +83,7 @@ Redux Toolkit 结合 Redux Persist 管理以下状态:
## 基础设施
| 组件 | 技术 |
|---|---|
| -------- | ---------------------------------------- |
| 数据库 | PostgreSQL(使用 Flyway 进行数据库迁移) |
| 缓存 | Redis(会话和 token 存储) |
| 文件存储 | AWS S3(枪械图片) |
@@ -26,7 +26,7 @@ Delta Force Guide 是一个全栈 Web 应用,为游戏 Delta Force(三角洲
## 架构
| 组件 | 技术栈 |
|---|---|
| -------- | --------------------------------------------------------------------------------------------------- |
| **前端** | React 19、TypeScript、Tailwind CSS 4、Ant Design 6、React Router 7、Redux Toolkit、TanStack Virtual |
| **后端** | Spring Boot 3、Java 21、PostgreSQL、MyBatis、Flyway、Redis |
| **认证** | JWT(access 和 refresh token)、验证码集成 |
@@ -7,7 +7,7 @@ title: OnixByte Toolbox API
所有模块均在 `com.onixbyte` group ID 下发布。每个模块有自己独立的基础包:
| 模块 | Maven Artifact | 基础包 |
|---|---|---|
| ------------------ | -------------------- | -------------------------------- |
| Common Toolbox | `common-toolbox` | `com.onixbyte.common` |
| Crypto Toolbox | `crypto-toolbox` | `com.onixbyte.crypto` |
| Math Toolbox | `math-toolbox` | `com.onixbyte.math` |
@@ -29,7 +29,7 @@ import com.onixbyte.common.adapter.ObjectMapAdapter;
### 工具类
| 类 | 描述 |
|---|---|
| ---------------- | ------------------------------------------- |
| `AesUtil` | AES 对称加密/解密,支持密钥生成 |
| `Base64Util` | Base64 编解码,支持多种字符集 |
| `BoolUtil` | 布尔值解析与转换工具 |
@@ -71,7 +71,7 @@ var grouped = CollectionUtil.groupBy(users, User::getDepartment);
### 密钥加载器
| 类 | 描述 |
|---|---|
| --------------------- | ---------------------------- |
| `RSAPrivateKeyLoader` | 从 PEM 字符串加载 RSA 私钥 |
| `RSAPublicKeyLoader` | 从 PEM 字符串加载 RSA 公钥 |
| `ECPrivateKeyLoader` | 从 PEM 字符串加载 ECDSA 私钥 |
@@ -100,7 +100,7 @@ var ecPublicKey = new ECPublicKeyLoader().load(pemString);
### 异常
| 类 | 描述 |
|---|---|
| --------------------- | -------------------------- |
| `KeyLoadingException` | PEM 格式密钥解析失败时抛出 |
---
@@ -112,7 +112,7 @@ var ecPublicKey = new ECPublicKeyLoader().load(pemString);
### 核心类
| 类 | 描述 |
|---|---|
| ---------------------- | ------------------------------------------------------------- |
| `Calculator` | 统计计算器 — 均值、中位数、方差、标准差、总和、最小值、最大值 |
| `PercentileCalculator` | 百分位数计算器,支持可配置的插值策略 |
@@ -136,7 +136,7 @@ double p99 = calculator.calculate(99);
### 数据模型
| 类 | 描述 |
|---|---|
| ---------------- | --------------------------------------------- |
| `QuartileBounds` | 包含 Q1、中位数(Q2)、Q3 值及 IQR 和须线边界 |
---
@@ -148,7 +148,7 @@ double p99 = calculator.calculate(99);
### 类
| 类 | 类型参数 | 可变性 |
|---|---|---|
| -------------------------- | -------- | ------ |
| `Tuple<A, B>` | 两个元素 | 可变 |
| `ImmutableTuple<A, B>` | 两个元素 | 不可变 |
| `Triple<A, B, C>` | 三个元素 | 可变 |
@@ -184,7 +184,7 @@ Integer c = triple.getThird();
### 实现
| 类 | 描述 |
|---|---|
| ---------------------------- | --------------------------------------------- |
| `SequentialUuidGenerator` | 生成时间排序的顺序 UUID(优化数据库索引性能) |
| `SnowflakeIdentityGenerator` | 雪花算法分布式唯一 ID 生成 |
@@ -205,5 +205,5 @@ long id = generator.nextId(); // 64 位雪花 ID
### 异常
| 类 | 描述 |
|---|---|
| ----------------- | ------------------------------------------ |
| `TimingException` | 系统时钟回拨时抛出,保证 ID 唯一性不受影响 |
@@ -13,7 +13,7 @@ OnixByte Toolbox 是一个面向 Java 应用的开发工具包,提供了一系
## 模块
| 模块 | Artifact ID | 描述 |
|--------------------|----------------------|-----------------------------------|
| ------------------ | -------------------- | ----------------------------------------------------- |
| Common Toolbox | `common-toolbox` | 日常工具类 — AES 加密、哈希、Base64、集合、分支、范围 |
| Crypto Toolbox | `crypto-toolbox` | RSA 和 ECDSA 算法的公私钥加载 |
| Math Toolbox | `math-toolbox` | 统计计算、百分位数分析、四分位数计算 |
@@ -24,7 +24,7 @@ import { Tabs, Tab } from "@rspress/core/theme"
每个地区暴露四个属性:
| 属性 | 类型 | 描述 | 示例 |
|---|---|---|---|
| -------------- | ------ | ----------------------- | ---------------------------------- |
| `abbreviation` | String | ISO 3166-1 alpha-2 缩写 | `HK`、`US`、`GB`、`RU` |
| `code` | String | ISO 3166-1 alpha-3 代码 | `HKG`、`USA`、`GBR`、`RUS` |
| `callingCode` | String | E.164 国际拨号前缀 | `852`、`1`、`44`、`7` |
@@ -20,16 +20,8 @@ import { Tabs, Tab } from "@rspress/core/theme"
## 安装
<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>
## 使用
+1 -1
View File
@@ -2,4 +2,4 @@ export default {
plugins: {
"@tailwindcss/postcss": {},
},
};
}
+3 -3
View File
@@ -1,9 +1,9 @@
declare module '*.css';
declare module "*.css"
interface ImportMetaEnv {
readonly SSG_MD: boolean;
readonly SSG_MD: boolean
}
interface ImportMeta {
readonly env: ImportMetaEnv;
readonly env: ImportMetaEnv
}