Compare commits

...

22 Commits

Author SHA1 Message Date
siujamo 4c11976eb7 ci: replace GitHub Pages action with Gitea Actions for Vercel deployment
Deploy to Vercel / deploy (push) Successful in 1m24s
Switch from GitHub Pages deployments to Vercel via Gitea Actions CLI.
2026-06-04 13:02:30 +08:00
siujamo 44dc28dbb3 feat: add Vercel geo-redirect config for China mainland visitors
Deploy to GitHub Pages / build (push) Failing after 7m30s
Deploy to GitHub Pages / deploy (push) Has been skipped
Use vercel.json redirects with the x-vercel-ip-country header condition
to route mainland China visitors to the ICP-licenced server.
2026-05-27 10:04:29 +08:00
siujamo f71e557a31 docs: add readme 2026-05-27 09:22:41 +08:00
siujamo a38cb70a21 docs: rewrite README in British English 2026-05-27 09:21:12 +08:00
zihluwang e1d9349f67 ci: delete unused github action configuration file 2026-05-27 00:50:02 +08:00
zihluwang a33a357187 Create deploy-page.yml 2026-05-26 19:11:38 +08:00
zihluwang d0a31f777d ci: github actions trigger 2026-05-26 19:00:33 +08:00
zihluwang 742afb456d ci: add github actions to deploy pages to github pages 2026-05-26 18:52:17 +08:00
siujamo f6fc7eeaae feat: add Kbd component and blog post about IDEA schema validation bug
Add a Kbd component with macOS special key support (⌘, ⌥, ⌃, ⇧, etc.),
export it from theme/index.tsx for use in MDX files.

Add blog posts (EN + ZH) documenting the IntelliJ IDEA application.yaml
schema validation bug caused by an overly broad fileMatch pattern in
SchemaStore, along with the quick fix.
2026-05-26 17:54:50 +08:00
siujamo 59d7a3042a docs: add doc _Fix IntelliJ IDEA Missing Spring Boot application.yaml Code Completion_ 2026-05-26 16:32:40 +08:00
siujamo b4c9232d78 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	docs/en-gb/_nav.json
#	docs/zh-hans/_nav.json
#	i18n.json
2026-05-26 16:29:07 +08:00
zihluwang b051d8c235 docs: optimise docs 2026-05-23 15:07:43 +08:00
zihluwang 601625f09b docs: add project index pages with categorized listings 2026-05-23 09:37:33 +08:00
zihluwang 18f8792733 docs: add vite-plugins index and port-checker, update regions4j titles 2026-05-23 09:34:18 +08:00
zihluwang 37e5727179 docs: add regions4j documentation
Add English and Chinese docs for regions4j, a Java library providing
ISO 3166-1 regional metadata with Calendar Versioning.
2026-05-23 09:26:06 +08:00
zihluwang 5b7c24fb0d docs: add onixbyte-toolbox documentation
Add English and Chinese docs for the OnixByte Toolbox monorepo covering
all six modules: common-toolbox, crypto-toolbox, math-toolbox, tuple,
identity-generator, and version-catalogue.
2026-05-23 09:21:37 +08:00
zihluwang 7f91c2bc23 chore: clean up unused Tabs imports and Gradle Groovy tab 2026-05-23 09:10:24 +08:00
zihluwang 55479f2fca docs: add helix enterprise application template introduction
Add English and Chinese documentation for Helix, a full-stack enterprise
application template with Spring Boot backend and React frontend.
2026-05-23 09:09:15 +08:00
zihluwang ac8a2e90d8 docs: add delta-force-guide project documentation
Add English and Chinese docs for the Delta Force Guide full-stack app
(Spring Boot backend + React frontend) with architecture, API reference,
and live site link.
2026-05-23 08:57:35 +08:00
zihluwang 6449bc0e87 docs: add captcha project documentation
Add English and Chinese documentation for onixbyte/captcha library,
including overview (index.mdx) and full API reference (api.md).
2026-05-23 08:48:42 +08:00
zihluwang ad6a11b1b4 docs: add docs for calendar toolbox 2026-05-23 08:42:52 +08:00
zihluwang 453f20c902 refactor: re-organise file structure 2026-05-23 07:55:18 +08:00
39 changed files with 3281 additions and 32 deletions
+32
View File
@@ -0,0 +1,32 @@
name: Deploy to Vercel
on:
push:
branches: [main]
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
- name: Install pnpm
run: npm install -g pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm build
- name: Deploy to Vercel
run: npx vercel deploy --prod --yes --token ${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
+3
View File
@@ -12,3 +12,6 @@ doc_build/
.vscode/*
!.vscode/extensions.json
.idea
# Claude Code
.claude/settings.local.json
+1 -1
View File
@@ -1,4 +1,4 @@
MIT License
MIT Licence
Copyright (c) 2026 OnixByte
+37 -17
View File
@@ -1,29 +1,49 @@
# Rspress website
# OnixByte Homepage
## Setup
The official OnixByte site — a central hub for technical blogs, project documentation, and development standards.
Install the dependencies:
## Tech Stack
A static documentation site built with [Rspress](https://rspress.dev/), supporting bilingual content (`en-gb` / `zh-hans`). All pages are authored in Markdown / MDX.
## URLs
| Domain | Recommended For |
|--------------------------------------------------|--------------------------------|
| [onixbyte.cn](https://onixbyte.cn) | Users in China mainland |
| [onixbyte.com](https://onixbyte.com) | Users outside China mainland |
| [onixbyte.github.io](https://onixbyte.github.io) | Global (GitHub Pages fallback) |
## Local Development
```bash
npm install
pnpm install
pnpm dev # Start dev server with HMR
pnpm build # Production build, outputs to dist/
pnpm preview # Preview the production build locally
pnpm lint # ESLint
pnpm format # Prettier — format all files
```
## Get started
## Directory Structure
Start the dev server:
```bash
npm run dev
```
docs/
├── public/ # Static assets (logos, icons, etc.)
├── en-gb/ # English content
│ ├── blogs/ # Technical blog posts
│ ├── projects/ # Project documentation
│ └── notifications/ # Announcements
└── zh-hans/ # Simplified Chinese content
├── blogs/
├── projects/
└── notifications/
```
Build the website for production:
## Deployment
```bash
npm run build
```
Pushing to the `main` branch triggers a GitHub Actions workflow that builds the site and deploys it to GitHub Pages.
Preview the production build locally:
## Licence
```bash
npm run preview
```
MIT
+5 -5
View File
@@ -1,14 +1,14 @@
[
{
"text": "blogs",
"link": "/blogs/",
"activeMatch": "/blogs/"
},
{
"text": "projects",
"link": "/projects/",
"activeMatch": "/projects/"
},
{
"text": "blogs",
"link": "/blogs/",
"activeMatch": "/blogs/"
},
{
"text": "notifications",
"link": "/notifications/",
@@ -0,0 +1,58 @@
---
title: Fix IntelliJ IDEA Missing Spring Boot application.yaml Code Completion
tags:
- intellij-idea
- spring-boot
- yaml
- schema-validation
- troubleshooting
author:
name: Zihlu Wang
email: real@zihluwang.me
---
import { Kbd } from "@rspress/core/theme"
Recently, while developing a Spring Boot project in IntelliJ IDEA, I noticed that the smart code completion for `application.yaml` and `application.yml` had suddenly vanished. Worse, the editor was flooded with warnings reading:
> Schema validation: Missing required property 'kind' = 'Application'
## The Symptom
When opening any `application.yaml` or `application.yml` under `src/main/resources/`, IDEA would treat it as an Enonic XP application descriptor rather than a Spring Boot configuration file. All Spring-specific property hints were gone, replaced by schema validation errors complaining about a missing `kind` property — a field that has nothing to do with Spring Boot.
Restarting IDEA, invalidating caches, and re-importing the project made no difference. The problem persisted across restarts.
## The Quick Fix
After some digging, I found the culprit. IDEA downloads JSON Schemas from remote sources (specifically, the [SchemaStore](https://www.schemastore.org/) catalogue) and uses them to validate configuration files. A recent schema update had introduced a `fileMatch` pattern that was too aggressive.
To disable this behaviour immediately:
1. Open **Settings** (<Kbd>Ctrl</Kbd>+<Kbd>Alt</Kbd>+<Kbd>S</Kbd> for Windows / <Kbd mac="cmd" /> + <Kbd>,</Kbd> for macOS)
2. Navigate to **Languages & Frameworks → Schemas and DTDs → Remote JSON Schemas**
3. Uncheck **Allow downloading JSON Schemas from remote sources**
4. Click **OK**
Your Spring Boot configuration hints will return instantly.
## Root Cause
The real culprit traces back to **19 May 2026**, when a developer from [Enonic](https://www.enonic.com/) submitted a pull request to the SchemaStore repository ([PR #5704](https://github.com/SchemaStore/schemastore/pull/5704)) that added the Enonic XP application descriptor schema. The schema's `fileMatch` property was set to:
```json
"fileMatch": [
"**/src/main/resources/application.yaml",
"**/src/main/resources/application.yml"
]
```
This pattern is far too broad — it matches **every** `application.yaml` and `application.yml` placed under `src/main/resources/`, which happens to be exactly where Spring Boot projects store their configuration files. Once this schema was merged into SchemaStore, any IntelliJ IDEA instance with remote JSON schema downloading enabled would fetch it and begin validating Spring Boot configs against the Enonic XP schema.
The developer has since acknowledged the issue and submitted a follow-up fix ([PR #5711](https://github.com/SchemaStore/schemastore/pull/5711)) to tighten the `fileMatch` patterns. As of writing, the fix has not yet been merged into SchemaStore.
## Why This Matters
SchemaStore is a community-maintained catalogue of JSON Schemas used by many editors (VS Code, IntelliJ IDEA, Neovim, etc.) to provide validation and autocompletion for common configuration files. When a schema in this catalogue declares overly broad matching rules, it affects users across all platforms and editors — not just IDEA.
For Spring Boot developers, the takeaway is simple: if your `application.yaml` hints disappear overnight, check what schema your IDE thinks the file belongs to. It might not be Spring Boot at all.
+390
View File
@@ -0,0 +1,390 @@
---
title: Calendar Toolbox API
---
## Package Overview
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 |
| `com.onixbyte.calendar.property` | Calendar-level properties |
| `com.onixbyte.calendar.parameter` | iCalendar property parameters |
| `com.onixbyte.calendar.recurrence` | Recurrence rule types |
| `com.onixbyte.calendar.value` | Value types |
| `com.onixbyte.calendar.util` | Formatting utilities |
---
## Calendar
The top-level object representing an iCalendar (RFC 5545) VCALENDAR container.
```java
Calendar calendar = Calendar.builder()
.withCalendarScale(...)
.withMethod(...)
.withProductIdentifier(...)
.withVersion(...)
.withOwner(...)
.withPrimaryCalendar(...)
.withPublishedTTL(...)
.withCalendarDescription(...)
.withCalendarName(...)
.withCalendarId(...)
.withCustomProperties(...)
.withComponents(event, todo, ...)
.build();
String icsContent = calendar.formatted();
```
### Calendar Properties
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 |
| `Version` | `VERSION` | iCalendar version (e.g., 2.0) |
| `Owner` | `X-OWNER` | Owner of the calendar |
| `PrimaryCalendar` | `X-PRIMARY-CALENDAR` | Whether this is a primary calendar |
| `PublishedTTL` | `X-PUBLISHED-TTL` | Time-to-live for published calendar |
| `CalendarDescription` | `X-CALENDAR-DESC` | Calendar description |
| `CalendarName` | `X-CALENDAR-NAME` | Calendar name |
| `CalendarId` | `X-CALENDAR-ID` | Calendar identifier |
| `CustomCalendarProperty` | `X-*` | Custom calendar properties |
Custom properties are created using a builder:
```java
var customProp = CustomCalendarProperty.builder()
.withParameters(...)
.build("X-MY-PROPERTY", "my-value");
```
> Note: Custom property names **must** start with `X-`.
---
## Components
Components represent the core entities in an iCalendar object. Each component implements `CalendarComponent` and is rendered between `BEGIN:TYPE` and `END:TYPE` delimiters.
### Event (VEVENT)
Represents a scheduled event.
```java
Event event = Event.builder()
.withDateTimeStamp(dtstamp) // required
.withUniqueIdentifier(uid) // required
.withDateTimeStart(dtstart)
.withDateTimeEnd(dtend) // mutually exclusive with duration
.withDuration(duration) // mutually exclusive with dtend
.withSummary(summary)
.withDescription(description)
.withClassification(classification)
.withDateTimeCreated(dateTimeCreated)
.withGeographicPosition(geoPos)
.withLastModified(lastModified)
.withLocation(location)
.withOrganiser(organiser)
.withPriority(priority)
.withSequenceNumber(seqNumber)
.withStatus(status)
.withTimeTransparency(transparency)
.withUniformResourceLocator(url)
.withRecurrenceId(recurrenceId)
.withRecurrenceRule(rrule)
.withAttachments(attachments)
.withAttendees(attendees)
.withCategories(categories)
.withComments(comments)
.withContacts(contacts)
.withExceptionDateTimes(exDates)
.withRequestStatuses(statuses)
.withRelated(related)
.withResources(resources)
.withRecurrenceDateTimes(rDates)
.build();
```
### Todo (VTODO)
Represents a to-do item or task.
```java
Todo todo = Todo.builder()
.withDateTimeStamp(dtstamp) // required
.withUniqueIdentifier(uid) // required
.withSummary(summary)
.withDateTimeStart(dtstart)
.withDateTimeDue(due) // mutually exclusive with duration
.withDuration(duration) // mutually exclusive with due
.withDateTimeCompleted(completed)
.withPercentComplete(percent)
.withClassification(classification)
.withDateTimeCreated(created)
.withDescription(description)
.withGeographicPosition(geoPos)
.withLastModified(lastModified)
.withLocation(location)
.withOrganiser(organiser)
.withPriority(priority)
.withSequenceNumber(seq)
.withStatus(status)
.withRecurrenceId(recurId)
.withRecurrenceRule(rrule)
.withUniformResourceLocator(url)
.withAttachments(attachments)
.withAttendees(attendees)
.withCategories(categories)
.withComments(comments)
.withContacts(contacts)
.withExceptionDateTimes(exDates)
.withRequestStatuses(statuses)
.withRelatedToList(related)
.withResources(resources)
.withRecurrenceDateTimes(rDates)
.build();
```
### Journal (VJOURNAL)
Represents a journal entry or diary note.
```java
Journal journal = Journal.builder()
.withDateTimeStamp(dtstamp) // required
.withUniqueIdentifier(uid) // required
.withSummary(summary)
.withClassification(classification)
.withDateTimeCreated(created)
.withDateTimeStart(dtstart)
.withLastModified(lastModified)
.withOrganiser(organiser)
.withRecurrenceId(recurId)
.withSequenceNumber(seq)
.withStatus(status)
.withUniformResourceLocator(url)
.withRecurrenceRule(rrule)
.withAttachments(attachments)
.withAttendees(attendees)
.withCategories(categories)
.withComments(comments)
.withContacts(contacts)
.withDescriptions(descriptions)
.withExceptionDateTimes(exDates)
.withRelatedToList(related)
.withRecurrenceDate(rDates)
.withRequestStatuses(statuses)
.build();
```
### FreeBusy (VFREEBUSY)
Represents free/busy time information.
```java
FreeBusy freeBusy = FreeBusy.builder()
.withDateTimeStamp(dtstamp) // required
.withUniqueIdentifier(uid) // required
.withContact(contact)
.withDateTimeStart(dtstart)
.withDateTimeEnd(dtend)
.withOrganiser(organiser)
.withUniformResourceLocator(url)
.withAttendees(attendees)
.withComments(comments)
.withFreeBusyTimes(freeBusyTimes)
.withRequestStatuses(statuses)
.build();
```
### TimeZone (VTIMEZONE)
Defines time zone rules including standard and daylight saving time transitions.
```java
TimeZone timezone = TimeZone.builder()
.withTimeZoneIdentifier(tzId)
.withLastModified(lastModified)
.withTimeZoneUrl(tzUrl)
.withTimeZoneProperties(standardProp, daylightProp)
.build();
```
Time zone properties define the actual transition rules:
```java
TimeZoneProperty standard = TimeZoneProperty.builder()
.withDateTimeStart(dtstart)
.withTimeZoneOffsetTo(offsetTo)
.withTimeZoneOffsetFrom(offsetFrom)
.withRecurrenceRule(rrule)
.withTimeZoneNames(tzName)
.buildStandard(); // or buildDaylight()
TimeZoneProperty daylight = TimeZoneProperty.builder()
.withDateTimeStart(dtstart)
.withTimeZoneOffsetTo(offsetTo)
.withTimeZoneOffsetFrom(offsetFrom)
.buildDaylight();
```
### Alarm (VALARM)
Defines alarm/reminder notifications. Three alarm types are supported:
```java
// Audio alarm
Alarm audioAlarm = Alarm.builder()
.withTrigger(trigger)
.withDuration(duration)
.withRepeatCount(repeatCount)
.withAttachments(audioAttachment)
.buildAudio();
// Display alarm
Alarm displayAlarm = Alarm.builder()
.withTrigger(trigger)
.withDescription(description) // required
.withDuration(duration)
.withRepeatCount(repeatCount)
.buildDisplay();
// Email alarm
Alarm emailAlarm = Alarm.builder()
.withTrigger(trigger)
.withDescription(description) // required
.withSummary(summary) // required
.withAttendees(attendees) // required
.withDuration(duration)
.withRepeatCount(repeatCount)
.buildEmail();
```
---
## Component Properties
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 |
| `Categories` | `CATEGORIES` | Categories or tags |
| `Classification` | `CLASS` | Access classification (PUBLIC, PRIVATE, CONFIDENTIAL) |
| `Comment` | `COMMENT` | Comment |
| `Contact` | `CONTACT` | Contact information |
| `DateTimeCompleted` | `COMPLETED` | Completion date-time |
| `DateTimeCreated` | `CREATED` | Creation date-time |
| `DateTimeDue` | `DUE` | Due date-time |
| `DateTimeEnd` | `DTEND` | End date-time |
| `DateTimeStamp` | `DTSTAMP` | Date-time stamp |
| `DateTimeStart` | `DTSTART` | Start date-time |
| `Description` | `DESCRIPTION` | Description |
| `ExceptionDateTimes` | `EXDATE` | Exception date-times |
| `FreeBusyTime` | `FREEBUSY` | Free/busy time periods |
| `GeographicPosition` | `GEO` | Geographic position (lat/long) |
| `LastModified` | `LAST-MODIFIED` | Last modified date-time |
| `Location` | `LOCATION` | Location |
| `Organiser` | `ORGANIZER` | Event organiser |
| `PercentComplete` | `PERCENT-COMPLETE` | Completion percentage |
| `Priority` | `PRIORITY` | Priority level |
| `RecurrenceDateTimes` | `RDATE` | Recurrence date-times |
| `RecurrenceId` | `RECURRENCE-ID` | Recurrence instance identifier |
| `RecurrenceRule` | `RRULE` | Recurrence rule |
| `RelatedTo` | `RELATED-TO` | Related component reference |
| `RepeatCount` | `REPEAT` | Alarm repeat count |
| `RequestStatus` | `REQUEST-STATUS` | Request status |
| `Resources` | `RESOURCES` | Resources |
| `SequenceNumber` | `SEQUENCE` | Sequence number (revision) |
| `Status` | `STATUS` | Component status (TENTATIVE, CONFIRMED, CANCELLED, etc.) |
| `Summary` | `SUMMARY` | Title or summary |
| `TimeTransparency` | `TRANSP` | Time transparency (OPAQUE, TRANSPARENT) |
| `TimeZoneIdentifier` | `TZID` | Time zone identifier |
| `TimeZoneName` | `TZNAME` | Time zone name |
| `TimeZoneOffsetFrom` | `TZOFFSETFROM` | Time zone offset from UTC |
| `TimeZoneOffsetTo` | `TZOFFSETTO` | Time zone offset to UTC |
| `TimeZoneUrl` | `TZURL` | Time zone URL |
| `Trigger` | `TRIGGER` | Alarm trigger |
| `UniformResourceLocator` | `URL` | Associated URL |
| `UniqueIdentifier` | `UID` | Unique identifier |
| `CustomComponentProperty` | `X-*` | Custom component properties |
---
## Parameters
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.) |
| `CommonName` | `CN` | Common name |
| `Delegatees` | `DELEGATED-TO` | Delegatees |
| `Delegators` | `DELEGATED-FROM` | Delegators |
| `DirectoryEntryReference` | `DIR` | Directory entry URI |
| `FormatType` | `FMTTYPE` | Format type (MIME type) |
| `FreeBusyTimeType` | `FBTYPE` | Free/busy time type |
| `InlineEncoding` | `ENCODING` | Inline encoding (BASE64) |
| `Language` | `LANGUAGE` | Language |
| `Membership` | `MEMBER` | Group membership |
| `ParticipationRole` | `ROLE` | Participation role (CHAIR, REQ-PARTICIPANT, etc.) |
| `ParticipationStatus` | `PARTSTAT` | Participation status (ACCEPTED, DECLINED, etc.) |
| `RecurrenceIdentifierRange` | `RANGE` | Recurrence range (THISANDPRIOR, THISANDFUTURE) |
| `RelationshipType` | `RELTYPE` | Relationship type (PARENT, CHILD, SIBLING) |
| `RsvpExpectation` | `RSVP` | RSVP expectation (TRUE, FALSE) |
| `SentBy` | `SENT-BY` | Sent by |
| `TimeZoneIdentifier` | `TZID` | Time zone identifier |
| `ValueDataType` | `VALUE` | Value data type (DATE, DATE-TIME, etc.) |
---
## Recurrence Types
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) |
---
## Value Types
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 |
| `UtcOffset` | UTC offset value (e.g., `-05:00`, `+01:00`) |
---
## Formatted Output
All components and properties provide a `formatted()` method that returns an iCalendar-compliant string representation. The `Calendar.formatted()` method produces a complete `.ics` output wrapped in `BEGIN:VCALENDAR`/`END:VCALENDAR`.
```java
String ics = calendar.formatted();
// BEGIN:VCALENDAR
// CALSCALE:GREGORIAN
// METHOD:PUBLISH
// ...
// END:VCALENDAR
```
@@ -0,0 +1,102 @@
---
title: Calendar Toolbox
---
import { Tabs, Tab } from "@rspress/core/theme"
## Introduction
Calendar Toolbox is a Java library designed to simplify the creation of `.ics` files, adhering to the iCalendar specification (RFC 5545). This library provides developers with a straightforward API to generate calendar events that can be imported into popular calendar applications such as Microsoft Outlook, Google Calendar, and Apple Calendar.
With Calendar Toolbox, you can effortlessly create, customise, and export calendar event files programmatically, enabling integration of calendar functionalities into your Java applications with minimal effort.
## Features
- **Full RFC 5545 Compliance** — Supports standard iCalendar components including VEVENT, VTODO, VJOURNAL, VFREEBUSY, VTIMEZONE, and VALARM.
- **Fluent Builder Pattern** — All components and properties use builder pattern for readable and intuitive construction.
- **Type-Safe Properties** — Strongly typed properties and parameters ensure correctness at compile time.
- **Custom Extensions** — Support for custom `X-` properties at both calendar and component level.
- **Lightweight** — Zero external dependencies for core functionality.
## Installation
<Tabs>
<Tab label="Gradle with Kotlin DSL">
```kotlin title="build.gradle.kts"
dependencies {
implementation("com.onixbyte:calendar-toolbox:1.1.0")
}
```
</Tab>
<Tab label="Maven">
```xml title="pom.xml"
<dependencies>
<dependency>
<groupId>com.onixbyte</groupId>
<artifactId>calendar-toolbox</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
```
</Tab>
</Tabs>
## Quick Start
```java
import com.onixbyte.calendar.Calendar;
import com.onixbyte.calendar.component.Event;
import com.onixbyte.calendar.component.property.*;
import com.onixbyte.calendar.property.*;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
public class CalendarExample {
public static void main(String[] args) {
// Create required date-time properties
var now = ZonedDateTime.now(ZoneOffset.UTC);
var dtstamp = DateTimeStamp.of(now);
var uid = UniqueIdentifier.of("meeting-001@example.com");
var dtstart = DateTimeStart.of(
LocalDateTime.of(2025, 8, 15, 9, 0),
"America/New_York"
);
var dtend = DateTimeEnd.of(
LocalDateTime.of(2025, 8, 15, 10, 0),
"America/New_York"
);
var summary = Summary.of("Team Standup");
var description = Description.of("Daily team standup meeting.");
// Build the event
var event = Event.builder()
.withDateTimeStamp(dtstamp)
.withUniqueIdentifier(uid)
.withDateTimeStart(dtstart)
.withDateTimeEnd(dtend)
.withSummary(summary)
.withDescription(description)
.build();
// Build the calendar and output .ics content
var calendar = Calendar.builder()
.withCalendarScale(CalendarScale.of("GREGORIAN"))
.withMethod(Method.of("PUBLISH"))
.withProductIdentifier(ProductIdentifier.of("-//OnixByte//Calendar Toolbox//EN"))
.withVersion(Version.of("2.0"))
.withComponents(event)
.build();
System.out.println(calendar.formatted());
}
}
```
This produces an `.ics` string that can be saved to a file or sent via email.
## License
Calendar Toolbox is open-source software released under the MIT License.
+248
View File
@@ -0,0 +1,248 @@
---
title: Captcha API
---
## Package Overview
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 |
---
## Producer
The top-level interface responsible for creating CAPTCHA images with text drawn on them.
```java
Producer captcha = DefaultCaptchaProducer.builder()
.textProducer(textProducer)
.wordRenderer(wordRenderer)
.gimpyEngine(gimpyEngine)
.backgroundProducer(backgroundProducer)
.width(200)
.height(50)
.borderDrawn(true)
.borderColour(Color.BLACK)
.borderThickness(1)
.build();
String text = captcha.createText();
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 |
---
## Text
### TextProducer
Interface for creating CAPTCHA text strings.
```java
public interface TextProducer {
String getText();
}
```
#### DefaultTextProducer
Generates random text with configurable length and character set.
```java
DefaultTextProducer textProducer = DefaultTextProducer.builder()
.length(6) // default: 6
.chars("ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray()) // default: a-z, A-Z, 0-9
.build();
```
| Method | Default Value | Description |
|----------|-----------------------------------------------------------|--------------------------------|
| `length` | `6` | Length of generated text |
| `chars` | `a-z`, `A-Z`, `0-9` (62 characters) | Characters used for generation |
### WordRenderer
Interface for rendering text onto an image.
```java
public interface WordRenderer {
BufferedImage renderWord(String word, int width, int height);
}
```
#### DefaultWordRenderer
Renders text with configurable font, colour, and spacing.
```java
DefaultWordRenderer wordRenderer = DefaultWordRenderer.builder()
.fontSize(40) // default: 40
.fonts("Arial", "Courier") // default: Arial, Courier
.fontColour(Color.BLACK) // default: Color.BLACK
.charSpace(2) // default: 2
.fontStyle(FontStyle.BOLD) // default: FontStyle.BOLD
.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 |
### 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 |
---
## GimpyEngine
Interface for applying image distortion effects.
```java
public interface GimpyEngine {
BufferedImage getDistortedImage(BufferedImage baseImage);
}
```
### WaterRipple
Applies a water ripple distortion effect. Extends `AbstractGimpyEngine` and adds noise automatically.
```java
WaterRipple gimpy = WaterRipple.builder()
.noiseProducer(DefaultNoiseProducer.builder().build()) // default: DefaultNoiseProducer
.build();
```
| Method | Default Value | Description |
|-----------------|---------------------------------------------|------------------------------|
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | The noise producer to use |
### FishEyeGimpy
Applies a fish-eye distortion effect with horizontal and vertical lines over the image.
```java
FishEyeGimpy gimpy = FishEyeGimpy.builder()
.build();
```
### ShadowGimpy
Applies a shadow and ripple effect. Extends `AbstractGimpyEngine` and adds noise automatically.
```java
ShadowGimpy gimpy = ShadowGimpy.builder()
.noiseProducer(DefaultNoiseProducer.builder().build()) // default: DefaultNoiseProducer
.build();
```
| Method | Default Value | Description |
|-----------------|---------------------------------------------|------------------------------|
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | The noise producer to use |
---
## Noise
### NoiseProducer
Interface for adding noise to an image.
```java
public interface NoiseProducer {
void makeNoise(BufferedImage image, float factorOne, float factorTwo,
float factorThree, float factorFour);
}
```
#### DefaultNoiseProducer
Adds noise curves with configurable colour.
```java
DefaultNoiseProducer noise = DefaultNoiseProducer.builder()
.noiseColour(Color.BLACK) // default: Color.BLACK
.build();
```
| Method | Default Value | Description |
|---------------|---------------|---------------------|
| `noiseColour` | `Color.BLACK` | The noise colour |
#### NoNoiseProducer
A no-op implementation that does not add any noise to the image.
```java
NoiseProducer noise = NoNoiseProducer.builder()
.build();
```
---
## Background
### BackgroundProducer
Interface for adding background to an image.
```java
public interface BackgroundProducer {
BufferedImage addBackground(BufferedImage image);
}
```
#### DefaultBackgroundProducer
Creates a gradient background with configurable start and end colours.
```java
DefaultBackgroundProducer background = DefaultBackgroundProducer.builder()
.colourFrom(Color.WHITE) // default: Color.LIGHT_GRAY
.colourTo(Color.LIGHT_GRAY) // default: Color.WHITE
.build();
```
| Method | Default Value | Description |
|--------------|--------------------|---------------------------------|
| `colourFrom` | `Color.LIGHT_GRAY` | The starting colour of gradient |
| `colourTo` | `Color.WHITE` | The ending colour of gradient |
+89
View File
@@ -0,0 +1,89 @@
---
title: Captcha
---
import { Tabs, Tab } from "@rspress/core/theme"
## Introduction
Captcha is a Java library for generating CAPTCHA images. This project is a spiritual successor to Google's Kaptcha, modernised for contemporary development practices.
With Captcha, you can easily generate customisable CAPTCHA images with various distortion effects, noise, and background options to integrate into your Java applications.
## Features
- **Easy Integration** — Simple builder-based API for quick setup and configuration.
- **Customisable CAPTCHA Generation** — Configure text length, character sets, font styles, and colours.
- **Multiple Distortion Effects** — Choose from Water Ripple, Fish Eye, and Shadow effects.
- **Configurable Noise** — Add noise lines with custom colours, or disable noise entirely.
- **Gradient Backgrounds** — Customisable gradient background colours.
- **Clean, Modern Codebase** — Well-documented, type-safe, and easy to extend.
## Installation
<Tabs>
<Tab label="Gradle with Kotlin DSL">
```kotlin title="build.gradle.kts"
dependencies {
implementation("com.onixbyte:captcha:1.0.0")
}
```
</Tab>
<Tab label="Maven">
```xml title="pom.xml"
<dependencies>
<dependency>
<groupId>com.onixbyte</groupId>
<artifactId>captcha</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
```
</Tab>
</Tabs>
## Quick Start
```java
import com.onixbyte.captcha.Producer;
import com.onixbyte.captcha.background.BackgroundProducer;
import com.onixbyte.captcha.background.impl.DefaultBackgroundProducer;
import com.onixbyte.captcha.gimpy.GimpyEngine;
import com.onixbyte.captcha.gimpy.impl.WaterRipple;
import com.onixbyte.captcha.impl.DefaultCaptchaProducer;
import com.onixbyte.captcha.noise.NoiseProducer;
import com.onixbyte.captcha.noise.impl.DefaultNoiseProducer;
import com.onixbyte.captcha.text.TextProducer;
import com.onixbyte.captcha.text.WordRenderer;
import com.onixbyte.captcha.text.impl.DefaultTextProducer;
import com.onixbyte.captcha.text.impl.DefaultWordRenderer;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class CaptchaExample {
public static void main(String[] args) throws IOException {
// Create a CAPTCHA producer with default configurations
Producer captcha = DefaultCaptchaProducer.builder().build();
// Generate text and create the image
String captchaText = captcha.createText();
BufferedImage captchaImage = captcha.createImage(captchaText);
// Save the image to a file
ImageIO.write(captchaImage, "png", new File("captcha.png"));
System.out.println("CAPTCHA text: " + captchaText);
}
}
```
This generates a CAPTCHA image with a 6-character random text and saves it as a PNG file.
## License
Captcha is open-source software released under the MIT License.
@@ -0,0 +1,91 @@
---
title: Delta Force Guide API
---
## Backend API Overview
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 |
## 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 |
### 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 |
### 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 |
| `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 |
## 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 |
## Frontend State Management
Redux Toolkit with Redux Persist manages:
- **Auth state** — Access tokens, refresh tokens, user profile
- **Settings state** — User preferences persisted to local storage
## API Client
The frontend uses a shared `WebClient` wrapper around Axios that handles:
- Base URL configuration (pointing to the backend API)
- JWT access token injection via request interceptors
- Automatic token refresh on 401 responses
## 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 |
@@ -0,0 +1,46 @@
---
title: Delta Force Guide
---
## Introduction
Delta Force Guide is a full-stack web application providing a searchable library of firearm modification codes for the game Delta Force. It consists of two components:
- **Web Frontend** — A React-based SPA for browsing, filtering, and copying modification codes.
- **Backend Server** — A Spring Boot REST API handling data persistence, authentication, and content management.
The live site is available at **[dfguide.onixbyte.cn](https://dfguide.onixbyte.cn)**.
## Features
- **Firearm Browser** — Browse a curated list of in-game firearms with detailed stats.
- **Modification Code Library** — Search and filter modification codes by weapon, mode, and tags.
- **One-Click Copy** — Copy modification codes directly from the interface.
- **Efficient Rendering** — Large lists rendered smoothly with window virtualisation.
- **Authentication** — User login with JWT-based auth and CAPTCHA verification.
- **Admin Panel** — Full CRUD operations for firearms and modification data.
- **Static-Friendly** — Frontend deployed as a static site with API proxy.
## 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 |
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.
## Repositories
- [delta-force-guide-server](https://github.com/onixbyte/delta-force-guide-server) — Spring Boot backend
- [delta-force-guide-web](https://github.com/onixbyte/delta-force-guide-web) — React frontend
## Quick Links
- **Live Site:** [dfguide.onixbyte.cn](https://dfguide.onixbyte.cn)
## License
Delta Force Guide is open-source software released under the MIT Licence.
+71
View File
@@ -0,0 +1,71 @@
---
title: Helix
---
## Introduction
Helix is a full-stack enterprise application template designed to accelerate the development of production-grade business applications. It provides a pre-built foundation with all the essential features an enterprise application needs, allowing teams to focus on business logic rather than infrastructure.
The project consists of two components:
- **Helix Server** — A Spring Boot backend providing REST APIs, authentication, authorisation, and data management.
- **Helix Web** — A React-based SPA frontend with a modern UI, role-based routing, and enterprise identity integration.
Helix is intended to be used as a starting point. Fork or clone it and begin building your own domain-specific features on top of the ready-made foundation.
## Features
### Backend (Helix Server)
- **Authentication & Authorisation** — JWT-based access and refresh token flow with Spring Security. Supports Microsoft Entra ID (Azure AD) integration.
- **Role-Based Access Control** — Fine-grained permissions via roles, authorities, and menu-level access control.
- **User & Organisation Management** — Full CRUD for users, departments, positions, and roles.
- **Menu Management** — Hierarchical menu tree with configurable visibility per role.
- **Asset Management** — File uploads to AWS S3 with CDN-ready prefix handling.
- **Settings Management** — Typed application settings persisted to database.
- **Captcha Integration** — Image CAPTCHA verification for login and registration flows.
- **Redis Caching** — High-performance caching with configurable TTL and custom serialisers.
- **Data Access** — Hybrid persistence with Spring Data JPA and MyBatis.
- **Validation** — Bean Validation groups with custom validation constraints.
### Frontend (Helix Web)
- **Enterprise Identity** — Microsoft Entra ID login via MSAL. Extensible social login provider architecture (Microsoft, Google, GitLab, Slack, Discord, DingTalk, Lark, WeCom, email/password).
- **Dashboard Layout** — Responsive admin dashboard with collapsible sidebar and role-based menu rendering.
- **User Management** — Data table with search, pagination, add/edit dialogues, role assignment, and phone number validation.
- **Role & Menu Management** — Role CRUD with authority assignment. Tree-based menu configuration.
- **Department & Position** — Organisation hierarchy management interfaces.
- **Protected Routing** — Route guards checking authentication and authorisation before page load.
- **State Management** — Redux Toolkit with Redux Persist for auth token persistence.
- **HTTP Client** — Axios wrapper with automatic JWT token injection and 401 refresh handling.
## Architecture
| Layer | Technology |
|--------------|---------------------------------------------------------------|
| **Frontend** | React 19, TypeScript, Tailwind CSS 4, Ant Design 6, React Router 7, Redux Toolkit, Axios, MSAL |
| **Backend** | Spring Boot 3.5, Java 17, Spring Security, MyBatis, Spring Data JPA |
| **Database** | PostgreSQL (with Flyway migrations) |
| **Cache** | Redis (session/token storage) |
| **Storage** | AWS S3 (asset uploads) |
The frontend communicates with the backend via a RESTful JSON API. Authentication flow uses JWT access tokens (short-lived) with refresh tokens stored in Redis. Microsoft Entra ID integration is handled client-side via MSAL and validated server-side.
## Repositories
- [helix-server](https://git.onixbyte.cn/helix/helix-server) — Spring Boot backend
- [helix-web](https://git.onixbyte.cn/helix/helix-web) — React frontend
## Getting Started
Helix is designed as a template project. To start a new project:
1. Fork or clone both `helix-server` and `helix-web` repositories.
2. Configure your database, Redis, and S3 settings in the backend.
3. Configure your authentication providers and API base URL in the frontend.
4. Run the backend: `./gradlew bootRun`
5. Run the frontend: `pnpm install && pnpm dev`
## License
Helix is open-source software released under the MIT License.
+21
View File
@@ -0,0 +1,21 @@
---
title: Projects
---
Explore open-source projects developed by OnixByte.
## Libraries & Toolkits
- **[OnixByte Toolbox](/projects/onixbyte-toolbox)** — A development kit for Java applications: AES, hashing, Base64, collection utilities, crypto key loaders, statistical calculators, identity generators, and generic tuples.
- **[regions4j](/projects/regions4j)** — Type-safe ISO 3166-1 regional metadata as a Java enum with O(1) lookups, E.164 dialling codes, and locale tags.
- **[Captcha](/projects/captcha)** — A modern Java CAPTCHA generation library with water ripple, fish-eye, and shadow distortion effects.
- **[Calendar Toolbox](/projects/calendar-toolbox)** — A Java library for creating `.ics` files conforming to the iCalendar specification (RFC 5545).
## Full-Stack Applications
- **[Helix](/projects/helix)** — An enterprise application template with Spring Boot backend and React frontend, featuring JWT auth, RBAC, user and organisation management, and Microsoft Entra ID integration.
- **[Delta Force Guide](/projects/delta-force-guide)** — A web app providing a searchable library of firearm modification codes for the game _Delta Force: Havvk Ops_, with a React SPA and Spring Boot REST API.
## Vite Plugins
- **[Port Checker](/projects/vite-plugins/port-checker)** — Warns when the Vite dev server listens on a browser-restricted port, preventing silent connection failures.
+209
View File
@@ -0,0 +1,209 @@
---
title: OnixByte Toolbox API
---
## Package Overview
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` |
---
## Common Toolbox
### Adapter
`ObjectMapAdapter` — Converts between objects and maps. Useful for serialisation or data transformation scenarios where key-value representations are preferred.
```java
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 |
**AesUtil Example:**
```java
var key = AesUtil.generateKey();
var encrypted = AesUtil.encrypt("hello world", key);
var decrypted = AesUtil.decrypt(encrypted, key);
```
**HashUtil Example:**
```java
var md5 = HashUtil.md5("hello world");
var sha256 = HashUtil.sha256("hello world");
var fileSha = HashUtil.sha256(new File("data.bin"));
```
**CollectionUtil Example:**
```java
var partitioned = CollectionUtil.partition(list, 100);
var grouped = CollectionUtil.groupBy(users, User::getDepartment);
```
---
## Crypto Toolbox
Provides a clean abstraction for loading cryptographic keys in PEM format. Supports both RSA and ECDSA algorithms.
### 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 |
All key loaders implement either `PrivateKeyLoader` or `PublicKeyLoader` interfaces.
**RSA Example:**
```java
var privateKey = new RSAPrivateKeyLoader().load(pemString);
var publicKey = new RSAPublicKeyLoader().load(pemString);
```
**ECDSA Example:**
```java
var ecPrivateKey = new ECPrivateKeyLoader().load(pemString);
var ecPublicKey = new ECPublicKeyLoader().load(pemString);
```
### Utility
`CryptoUtil` — Provides convenient methods for digital signature creation and verification, as well as general-purpose cryptographic helpers.
### Exceptions
| Class | Description |
|------------------------|---------------------------------------------------|
| `KeyLoadingException` | Thrown when a PEM-formatted key fails to parse |
---
## Math Toolbox
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 |
**Calculator Example:**
```java
var stats = new Calculator(Arrays.asList(1.0, 2.0, 3.0, 4.0, 5.0));
double mean = stats.getMean();
double median = stats.getMedian();
double stdDev = stats.getStandardDeviation();
```
**PercentileCalculator Example:**
```java
var calculator = new PercentileCalculator(data);
double p95 = calculator.calculate(95);
double p99 = calculator.calculate(99);
```
### Model
| Class | Description |
|-------------------|----------------------------------------------------------------|
| `QuartileBounds` | Holds Q1, median (Q2), Q3 values along with IQR and whisker bounds |
---
## Tuple
Lightweight generic tuple types for when you need to return multiple values without defining a dedicated class.
### 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 |
**Example:**
```java
var pair = Tuple.of("key", 42);
var triple = Triple.of("id", "name", 100);
var immutable = ImmutableTuple.of("constant", true);
// Accessors
String first = pair.getFirst();
Integer second = pair.getSecond();
// Triple accessors
String a = triple.getFirst();
String b = triple.getSecond();
Integer c = triple.getThird();
```
---
## Identity Generator
Generates unique identifiers suitable for use as database primary keys or distributed IDs.
### Interface
`IdentityGenerator<T>` — Generates identities of type `T`.
### Implementations
| Class | Description |
|------------------------------|-----------------------------------------------------------------|
| `SequentialUuidGenerator` | Generates time-ordered, sequential UUIDs (optimised for DB indexes) |
| `SnowflakeIdentityGenerator` | Snowflake-style distributed unique ID generation |
**Sequential UUID:**
```java
var generator = new SequentialUuidGenerator();
UUID id = generator.nextId(); // time-ordered UUID, B-tree friendly
```
**Snowflake:**
```java
var generator = new SnowflakeIdentityGenerator(workerId, datacenterId);
long id = generator.nextId(); // 64-bit snowflake ID
```
### Exceptions
| Class | Description |
|-------------------|----------------------------------------------------------------|
| `TimingException` | Thrown when the system clock moves backwards, compromising ID uniqueness |
@@ -0,0 +1,54 @@
---
title: OnixByte Toolbox
---
import { Tabs, Tab } from "@rspress/core/theme"
## Introduction
OnixByte Toolbox is a Development Kit for Java applications that provides a set of convenient, reusable tools for writing code efficiently. It is designed and maintained by OnixByte as a monorepo containing multiple purpose-built libraries, each addressing a specific development need — from common utilities and cryptography to mathematical computation and identity generation.
The toolkit is available on Maven Central under the `com.onixbyte` group ID. Each module is independently versioned and can be included in any Java 17+ project.
## 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 |
| Tuple | `tuple` | Generic 2-tuple and 3-tuple with immutable variants |
| Identity Generator | `identity-generator` | Snowflake-style and sequential UUID identity generation |
| Version Catalogue | `version-catalogue` | Centralised Gradle version catalogue for OnixByte projects |
## Installation
Add the desired module as a dependency in your build config:
<Tabs>
<Tab label="Gradle with Kotlin DSL">
```kotlin title="build.gradle.kts"
dependencies {
implementation("com.onixbyte:$artefactId:$version")
}
```
</Tab>
<Tab label="Maven">
```xml title="pom.xml"
<dependency>
<groupId>com.onixbyte</groupId>
<artifactId>${artefactId}</artifactId>
<version>${version}</version>
</dependency>
```
</Tab>
</Tabs>
## Requirements
- Java 17 or later
## License
OnixByte Toolbox is open-source software released under the MIT Licence.
+98
View File
@@ -0,0 +1,98 @@
---
title: Regions for Java
---
## Introduction
**regions4j** is a lightweight, type-safe Java library that provides comprehensive metadata for world regions based on the ISO 3166-1 standard. It is designed to simplify internationalisation (i18n), telecommunication routing, and regional data management in Java-based enterprise applications.
The library models every ISO 3166-1 country and territory as an enum constant, giving you compile-time safety and IDE autocompletion when referencing regions. With built-in O(1) lookups, zero external dependencies, and Java 8 compatibility, it is suitable for projects of any size — from microservices to monolithic enterprise systems.
## Features
- **ISO 3166-1 Compliant** — Full support for Alpha-2 (`abbreviation`) and Alpha-3 (`code`) formats across all assigned countries and territories.
- **Telecommunication Metadata** — Includes E.164 international dialling prefixes for every region.
- **Locality Support** — Default locale tags (`zh_HK`, `en_US`, `en_GB`, etc.) for each region to assist with i18n workflows.
- **High Performance** — Thread-safe, immutable internal hash maps provide constant-time lookups by abbreviation or code.
- **Zero Dependencies** — A pure Java library with no external overhead.
- **Calendar Versioning** — Versions follow a `YYYY.MM` scheme (e.g. `2025.12`) to transparently indicate the freshness of the underlying ISO data, rather than semantic versioning.
## Core Schema
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` |
| `locale` | String | Default language and region tag | `zh_HK`, `en_US`, `en_GB`, `ru_RU` |
## Installation
**Maven:**
```xml
<dependency>
<groupId>com.onixbyte</groupId>
<artifactId>regions4j</artifactId>
<version>2025.12</version>
</dependency>
```
**Gradle (Kotlin DSL):**
```kotlin
implementation("com.onixbyte:regions4j:2025.12")
```
> **Versioning note:** This library uses Calendar Versioning (`YYYY.MM`) rather than Semantic Versioning. A version string like `2025.12` tells you immediately that the regional data reflects the ISO 3166-1 state as of December 2025.
## Usage
### Direct Access
Reference any region directly via its enum constant:
```java
Region uk = Region.UNITED_KINGDOM;
uk.getAbbreviation(); // "GB"
uk.getCode(); // "GBR"
uk.getDialCode(); // "44"
uk.getLocale(); // "en_GB"
```
### Efficient Lookups
Look up regions from string inputs — ideal for processing web requests, API payloads, or database records:
```java
// By Alpha-2 abbreviation (case-sensitive)
Region region = Region.fromAbbreviation("HK");
// By Alpha-3 code (case-insensitive)
Region region = Region.fromCode("HKG");
```
### Java Locale Integration
Convert a region's locale string to a `java.util.Locale` for use with standard Java i18n APIs:
```java
Region region = Region.CHINA;
Locale javaLocale = Locale.forLanguageTag(region.getLocale().replace("_", "-"));
javaLocale.getDisplayCountry(Locale.UK); // "China"
```
## Performance
On first access, the library initialises all regions into immutable `HashMap` structures. Subsequent lookups via `fromAbbreviation()` and `fromCode()` are thread-safe and run in constant time — suitable for high-throughput request paths.
## Requirements
- Java 8 or later
## License
regions4j is open-source software released under the MIT License.
@@ -0,0 +1,11 @@
---
title: Vite Plugins
---
## Overview
A collection of Vite plugins developed and maintained by OnixByte. Each plugin is designed to solve a specific problem in the Vite development workflow — lightweight, zero-dependency, and plug-and-play.
## Available Plugins
- **[Port Checker](/projects/vite-plugins/port-checker)** — Warns when the dev server listens on a browser-restricted port (per the Fetch specification), helping you avoid silent connection failures.
@@ -0,0 +1,68 @@
---
title: Port Checker
---
import { Tabs, Tab } from "@rspress/core/theme"
## Introduction
**vite-plugin-port-checker** is a lightweight Vite plugin that warns you when the dev server is listening on a port blocked by common browsers. Browsers such as Chrome and Firefox maintain a [list of restricted ports](https://fetch.spec.whatwg.org/#port-blocking) — typically those associated with well-known protocols like SMTP, SSH, and DNS — and refuse to connect to them. Accidentally running your dev server on one of these ports leads to a confusing "connection refused" or "blocked" error with no clear explanation.
This plugin detects the situation at startup and prints a clear, colour-coded warning to the console, advising you to change the `server.port` setting in your Vite configuration.
## Features
- **Automatic Detection** — Checks the dev server port against the complete Fetch spec port-blocking list (68 restricted ports).
- **Clear Warnings** — Yellow-highlighted console output with actionable guidance.
- **Zero Configuration** — Works out of the box with no options to set.
- **Lightweight** — Single-file plugin with no dependencies beyond Vite itself.
## 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>
</Tabs>
## Usage
Add the plugin to your `vite.config.ts`:
```ts
// vite.config.ts
import { defineConfig } from "vite"
import checkRestrictedPort from "vite-plugin-port-checker"
export default defineConfig({
plugins: [checkRestrictedPort()],
})
```
When the dev server starts on a restricted port (e.g. port 25, 22, or 53), you will see:
```
[Warning] The current listening port 25 is categorised as a restricted port
by most browsers. This may prevent you from accessing the application.
Please consider changing the port in your 'vite.config.ts' or 'vite.config.js'
via 'server.port'.
```
## How It Works
The plugin hooks into Vite's `configureServer` lifecycle. Once the HTTP server emits the `listening` event, the plugin inspects the bound port and checks it against the hardcoded set of 68 restricted ports defined in the [Fetch specification](https://fetch.spec.whatwg.org/#port-blocking). If there is a match, a yellow `console.warn` message alerts the developer.
## Requirements
- Vite 3.0.0 or later
## License
vite-plugin-port-checker is open-source software released under the MIT License.
+5 -5
View File
@@ -1,14 +1,14 @@
[
{
"text": "blogs",
"link": "/blogs/",
"activeMatch": "/blogs/"
},
{
"text": "projects",
"link": "/projects/",
"activeMatch": "/projects/"
},
{
"text": "blogs",
"link": "/blogs/",
"activeMatch": "/blogs/"
},
{
"text": "notifications",
"link": "/notifications/",
@@ -0,0 +1,58 @@
---
title: 修复 IntelliJ IDEA 中 Spring Boot 的 application.yaml 智能提示消失问题
tags:
- intellij-idea
- spring-boot
- yaml
- schema-validation
- troubleshooting
author:
name: Zihlu Wang
email: real@zihluwang.me
---
import { Kbd } from "@rspress/core/theme"
最近在使用 IDEA 开发 Spring Boot 项目时,我发现 `application.yaml` 和 `application.yml` 的智能代码提示突然消失了。更糟糕的是,编辑器中充满了如下警告:
> `Schema validation: Missing required property 'kind' = 'Application'`
## 症状
打开 `src/main/resources/` 下的 `application.yaml` 或 `application.yml` 文件时,IDEA 会将其视为 Enonic XP 应用描述文件,而非 Spring Boot 配置文件。所有 Spring 特有的属性提示全部消失,取而代之的是一堆要求填写 `kind` 属性的 Schema 校验错误——这个字段与 Spring Boot 毫无关系。
重启 IDEA、清除缓存、重新导入项目都无济于事,问题依旧存在。
## 快速修复
经过一番排查,我找到了罪魁祸首。IDEA 会从远程源(具体来说是 [SchemaStore](https://www.schemastore.org/) 目录)下载 JSON Schema,并用它们来校验配置文件。最近的一次 Schema 更新引入了一个匹配范围过大的 `fileMatch` 模式。
要立即禁用此行为:
1. 打开 **Settings**Windows<Kbd>Ctrl</Kbd>+<Kbd>Alt</Kbd>+<Kbd>S</Kbd> / macOS<Kbd mac="cmd" /> + <Kbd>,</Kbd>
2. 导航至 **Languages & Frameworks → Schemas and DTDs → Remote JSON Schemas**
3. 取消勾选 **Allow downloading JSON Schemas from remote sources**
4. 点击 **OK**
Spring Boot 的配置提示会立刻恢复。
## 根本原因
事情的根源要追溯到 **2026 年 5 月 19 日**,一位来自 [Enonic](https://www.enonic.com/) 的开发者向 SchemaStore 仓库提交了一个 PR[PR #5704](https://github.com/SchemaStore/schemastore/pull/5704)),添加了 Enonic XP 应用描述文件的 Schema。该 Schema 的 `fileMatch` 属性被设置为:
```json
"fileMatch": [
"**/src/main/resources/application.yaml",
"**/src/main/resources/application.yml"
]
```
这个匹配模式过于宽泛——它匹配了 **所有** 位于 `src/main/resources/` 下的 `application.yaml` 和 `application.yml` 文件,而这正是 Spring Boot 项目存放配置文件的位置。一旦该 Schema 被合并到 SchemaStore 中,任何启用了远程 JSON Schema 下载功能的 IntelliJ IDEA 都会拉取它,并开始用 Enonic XP 的 Schema 来校验 Spring Boot 的配置。
该开发者已意识到问题,并提交了后续修复 PR[PR #5711](https://github.com/SchemaStore/schemastore/pull/5711))来收紧 `fileMatch` 匹配规则。截至本文撰写时,该修复尚未被 SchemaStore 合并。
## 为什么这很重要
SchemaStore 是一个由社区维护的 JSON Schema 目录,被许多编辑器(VS Code、IntelliJ IDEA、Neovim 等)用来为常见配置文件提供校验和自动补全功能。当该目录中的某个 Schema 声明了过于宽泛的匹配规则时,会影响到所有平台、所有编辑器的用户——不仅仅是 IDEA。
对于 Spring Boot 开发者来说,结论很简单:如果你的 `application.yaml` 提示一夜之间消失了,先检查一下你的 IDE 认为该文件属于哪个 Schema,它可能根本不是 Spring Boot。
-3
View File
@@ -8,9 +8,6 @@ hero:
- theme: brand
text: 探索项目
link: https://github.com/onixbyte
- theme: alt
text: 体验 Dev Lab
link: https://dev-lab.onixbyte.dev
features:
- title: OnixByte Toolbox
details: 一个多功能 Java 类库,为现代 Java 开发提供通用工具,无缝集成 Spring 生态。已上架 Maven Central。
@@ -0,0 +1,390 @@
---
title: Calendar Toolbox API
---
## 包结构概览
库的代码组织在基础包 `com.onixbyte.calendar` 下,结构如下:
| 包 | 描述 |
|---|---|
| `com.onixbyte.calendar` | 根日历对象 |
| `com.onixbyte.calendar.component` | iCalendar 组件(VEVENT、VTODO 等) |
| `com.onixbyte.calendar.component.property` | 组件级属性 |
| `com.onixbyte.calendar.property` | 日历级属性 |
| `com.onixbyte.calendar.parameter` | iCalendar 属性参数 |
| `com.onixbyte.calendar.recurrence` | 重复规则类型 |
| `com.onixbyte.calendar.value` | 值类型 |
| `com.onixbyte.calendar.util` | 格式化工具类 |
---
## Calendar
表示 iCalendarRFC 5545VCALENDAR 容器的顶层对象。
```java
Calendar calendar = Calendar.builder()
.withCalendarScale(...)
.withMethod(...)
.withProductIdentifier(...)
.withVersion(...)
.withOwner(...)
.withPrimaryCalendar(...)
.withPublishedTTL(...)
.withCalendarDescription(...)
.withCalendarName(...)
.withCalendarId(...)
.withCustomProperties(...)
.withComponents(event, todo, ...)
.build();
String icsContent = calendar.formatted();
```
### 日历属性
所有日历级属性位于 `com.onixbyte.calendar.property`,实现 `CalendarProperty` 接口。
| 类 | iCalendar 属性 | 描述 |
|---|---|---|
| `CalendarScale` | `CALSCALE` | 日历系统(例如 GREGORIAN |
| `Method` | `METHOD` | iCalendar 方法(例如 PUBLISH、REQUEST |
| `ProductIdentifier` | `PRODID` | 日历的产品标识符 |
| `Version` | `VERSION` | iCalendar 版本(例如 2.0 |
| `Owner` | `X-OWNER` | 日历所有者 |
| `PrimaryCalendar` | `X-PRIMARY-CALENDAR` | 是否为主日历 |
| `PublishedTTL` | `X-PUBLISHED-TTL` | 已发布日历的生存时间 |
| `CalendarDescription` | `X-CALENDAR-DESC` | 日历描述 |
| `CalendarName` | `X-CALENDAR-NAME` | 日历名称 |
| `CalendarId` | `X-CALENDAR-ID` | 日历标识符 |
| `CustomCalendarProperty` | `X-*` | 自定义日历属性 |
自定义属性使用 Builder 创建:
```java
var customProp = CustomCalendarProperty.builder()
.withParameters(...)
.build("X-MY-PROPERTY", "my-value");
```
> 注意:自定义属性名称**必须**以 `X-` 开头。
---
## 组件
组件是 iCalendar 对象的核心实体。每个组件实现 `CalendarComponent` 接口,并在 `BEGIN:TYPE``END:TYPE` 定界符之间渲染。
### EventVEVENT
表示一个预定的活动/事件。
```java
Event event = Event.builder()
.withDateTimeStamp(dtstamp) // 必需
.withUniqueIdentifier(uid) // 必需
.withDateTimeStart(dtstart)
.withDateTimeEnd(dtend) // 与 duration 互斥
.withDuration(duration) // 与 dtend 互斥
.withSummary(summary)
.withDescription(description)
.withClassification(classification)
.withDateTimeCreated(dateTimeCreated)
.withGeographicPosition(geoPos)
.withLastModified(lastModified)
.withLocation(location)
.withOrganiser(organiser)
.withPriority(priority)
.withSequenceNumber(seqNumber)
.withStatus(status)
.withTimeTransparency(transparency)
.withUniformResourceLocator(url)
.withRecurrenceId(recurrenceId)
.withRecurrenceRule(rrule)
.withAttachments(attachments)
.withAttendees(attendees)
.withCategories(categories)
.withComments(comments)
.withContacts(contacts)
.withExceptionDateTimes(exDates)
.withRequestStatuses(statuses)
.withRelated(related)
.withResources(resources)
.withRecurrenceDateTimes(rDates)
.build();
```
### TodoVTODO
表示待办事项或任务。
```java
Todo todo = Todo.builder()
.withDateTimeStamp(dtstamp) // 必需
.withUniqueIdentifier(uid) // 必需
.withSummary(summary)
.withDateTimeStart(dtstart)
.withDateTimeDue(due) // 与 duration 互斥
.withDuration(duration) // 与 due 互斥
.withDateTimeCompleted(completed)
.withPercentComplete(percent)
.withClassification(classification)
.withDateTimeCreated(created)
.withDescription(description)
.withGeographicPosition(geoPos)
.withLastModified(lastModified)
.withLocation(location)
.withOrganiser(organiser)
.withPriority(priority)
.withSequenceNumber(seq)
.withStatus(status)
.withRecurrenceId(recurId)
.withRecurrenceRule(rrule)
.withUniformResourceLocator(url)
.withAttachments(attachments)
.withAttendees(attendees)
.withCategories(categories)
.withComments(comments)
.withContacts(contacts)
.withExceptionDateTimes(exDates)
.withRequestStatuses(statuses)
.withRelatedToList(related)
.withResources(resources)
.withRecurrenceDateTimes(rDates)
.build();
```
### JournalVJOURNAL
表示日记条目或笔记。
```java
Journal journal = Journal.builder()
.withDateTimeStamp(dtstamp) // 必需
.withUniqueIdentifier(uid) // 必需
.withSummary(summary)
.withClassification(classification)
.withDateTimeCreated(created)
.withDateTimeStart(dtstart)
.withLastModified(lastModified)
.withOrganiser(organiser)
.withRecurrenceId(recurId)
.withSequenceNumber(seq)
.withStatus(status)
.withUniformResourceLocator(url)
.withRecurrenceRule(rrule)
.withAttachments(attachments)
.withAttendees(attendees)
.withCategories(categories)
.withComments(comments)
.withContacts(contacts)
.withDescriptions(descriptions)
.withExceptionDateTimes(exDates)
.withRelatedToList(related)
.withRecurrenceDate(rDates)
.withRequestStatuses(statuses)
.build();
```
### FreeBusyVFREEBUSY
表示空闲/忙碌时间信息。
```java
FreeBusy freeBusy = FreeBusy.builder()
.withDateTimeStamp(dtstamp) // 必需
.withUniqueIdentifier(uid) // 必需
.withContact(contact)
.withDateTimeStart(dtstart)
.withDateTimeEnd(dtend)
.withOrganiser(organiser)
.withUniformResourceLocator(url)
.withAttendees(attendees)
.withComments(comments)
.withFreeBusyTimes(freeBusyTimes)
.withRequestStatuses(statuses)
.build();
```
### TimeZoneVTIMEZONE
定义时区规则,包括标准时间和夏令时转换。
```java
TimeZone timezone = TimeZone.builder()
.withTimeZoneIdentifier(tzId)
.withLastModified(lastModified)
.withTimeZoneUrl(tzUrl)
.withTimeZoneProperties(standardProp, daylightProp)
.build();
```
时区属性定义实际的转换规则:
```java
TimeZoneProperty standard = TimeZoneProperty.builder()
.withDateTimeStart(dtstart)
.withTimeZoneOffsetTo(offsetTo)
.withTimeZoneOffsetFrom(offsetFrom)
.withRecurrenceRule(rrule)
.withTimeZoneNames(tzName)
.buildStandard(); // 或 buildDaylight()
TimeZoneProperty daylight = TimeZoneProperty.builder()
.withDateTimeStart(dtstart)
.withTimeZoneOffsetTo(offsetTo)
.withTimeZoneOffsetFrom(offsetFrom)
.buildDaylight();
```
### AlarmVALARM
定义闹钟/提醒通知。支持三种闹钟类型:
```java
// 音频闹钟
Alarm audioAlarm = Alarm.builder()
.withTrigger(trigger)
.withDuration(duration)
.withRepeatCount(repeatCount)
.withAttachments(audioAttachment)
.buildAudio();
// 显示闹钟
Alarm displayAlarm = Alarm.builder()
.withTrigger(trigger)
.withDescription(description) // 必需
.withDuration(duration)
.withRepeatCount(repeatCount)
.buildDisplay();
// 邮件闹钟
Alarm emailAlarm = Alarm.builder()
.withTrigger(trigger)
.withDescription(description) // 必需
.withSummary(summary) // 必需
.withAttendees(attendees) // 必需
.withDuration(duration)
.withRepeatCount(repeatCount)
.buildEmail();
```
---
## 组件属性
组件属性位于 `com.onixbyte.calendar.component.property`,实现 `ComponentProperty` 接口。
| 类 | iCalendar 属性 | 描述 |
|---|---|---|
| `Action` | `ACTION` | 闹钟操作类型(AUDIO、DISPLAY、EMAIL |
| `Attachment` | `ATTACH` | 文档附件 |
| `Attendee` | `ATTENDEE` | 事件/任务参与者 |
| `Categories` | `CATEGORIES` | 类别或标签 |
| `Classification` | `CLASS` | 访问分类(PUBLIC、PRIVATE、CONFIDENTIAL |
| `Comment` | `COMMENT` | 评论 |
| `Contact` | `CONTACT` | 联系信息 |
| `DateTimeCompleted` | `COMPLETED` | 完成日期时间 |
| `DateTimeCreated` | `CREATED` | 创建日期时间 |
| `DateTimeDue` | `DUE` | 截止日期时间 |
| `DateTimeEnd` | `DTEND` | 结束日期时间 |
| `DateTimeStamp` | `DTSTAMP` | 日期时间戳 |
| `DateTimeStart` | `DTSTART` | 开始日期时间 |
| `Description` | `DESCRIPTION` | 描述 |
| `ExceptionDateTimes` | `EXDATE` | 例外日期时间 |
| `FreeBusyTime` | `FREEBUSY` | 空闲/忙碌时间段 |
| `GeographicPosition` | `GEO` | 地理位置(纬度/经度) |
| `LastModified` | `LAST-MODIFIED` | 最后修改日期时间 |
| `Location` | `LOCATION` | 地点 |
| `Organiser` | `ORGANIZER` | 组织者 |
| `PercentComplete` | `PERCENT-COMPLETE` | 完成百分比 |
| `Priority` | `PRIORITY` | 优先级 |
| `RecurrenceDateTimes` | `RDATE` | 重复日期时间 |
| `RecurrenceId` | `RECURRENCE-ID` | 重复实例标识符 |
| `RecurrenceRule` | `RRULE` | 重复规则 |
| `RelatedTo` | `RELATED-TO` | 相关组件引用 |
| `RepeatCount` | `REPEAT` | 闹钟重复次数 |
| `RequestStatus` | `REQUEST-STATUS` | 请求状态 |
| `Resources` | `RESOURCES` | 资源 |
| `SequenceNumber` | `SEQUENCE` | 序列号(修订版本) |
| `Status` | `STATUS` | 组件状态(TENTATIVE、CONFIRMED、CANCELLED 等) |
| `Summary` | `SUMMARY` | 标题或摘要 |
| `TimeTransparency` | `TRANSP` | 时间透明度(OPAQUE、TRANSPARENT |
| `TimeZoneIdentifier` | `TZID` | 时区标识符 |
| `TimeZoneName` | `TZNAME` | 时区名称 |
| `TimeZoneOffsetFrom` | `TZOFFSETFROM` | 相对于 UTC 的时区偏移(原) |
| `TimeZoneOffsetTo` | `TZOFFSETTO` | 相对于 UTC 的时区偏移(目标) |
| `TimeZoneUrl` | `TZURL` | 时区 URL |
| `Trigger` | `TRIGGER` | 闹钟触发器 |
| `UniformResourceLocator` | `URL` | 关联 URL |
| `UniqueIdentifier` | `UID` | 唯一标识符 |
| `CustomComponentProperty` | `X-*` | 自定义组件属性 |
---
## 参数
参数位于 `com.onixbyte.calendar.parameter`,为组件属性提供额外限定。
| 类 | iCalendar 参数 | 描述 |
|---|---|---|
| `AlarmTriggerRelationship` | `RELATED` | 触发器关联(START、END |
| `AlternateTextRepresentation` | `ALTREP` | 替代文本 URI |
| `CalendarUserType` | `CUTYPE` | 日历用户类型(INDIVIDUAL、GROUP、RESOURCE 等) |
| `CommonName` | `CN` | 通用名称 |
| `Delegatees` | `DELEGATED-TO` | 受托人 |
| `Delegators` | `DELEGATED-FROM` | 委托人 |
| `DirectoryEntryReference` | `DIR` | 目录条目 URI |
| `FormatType` | `FMTTYPE` | 格式类型(MIME 类型) |
| `FreeBusyTimeType` | `FBTYPE` | 空闲/忙碌时间类型 |
| `InlineEncoding` | `ENCODING` | 内联编码(BASE64 |
| `Language` | `LANGUAGE` | 语言 |
| `Membership` | `MEMBER` | 组成员 |
| `ParticipationRole` | `ROLE` | 参与角色(CHAIR、REQ-PARTICIPANT 等) |
| `ParticipationStatus` | `PARTSTAT` | 参与状态(ACCEPTED、DECLINED 等) |
| `RecurrenceIdentifierRange` | `RANGE` | 重复范围(THISANDPRIOR、THISANDFUTURE |
| `RelationshipType` | `RELTYPE` | 关系类型(PARENT、CHILD、SIBLING |
| `RsvpExpectation` | `RSVP` | RSVP 期望(TRUE、FALSE |
| `SentBy` | `SENT-BY` | 发送者 |
| `TimeZoneIdentifier` | `TZID` | 时区标识符 |
| `ValueDataType` | `VALUE` | 值数据类型(DATE、DATE-TIME 等) |
---
## 递归类型
位于 `com.onixbyte.calendar.recurrence`
| 类 | 描述 |
|---|---|
| `Frequency` | 重复频率常量(DAILY、WEEKLY、MONTHLY、YEARLY),用于重复规则 |
| `WeekdayNum` | 重复规则的星期序号(例如第 2 个星期一) |
---
## 值类型
位于 `com.onixbyte.calendar.value`
| 类 | 描述 |
|---|---|
| `FreeBusyTimeValue` | 表示空闲/忙碌时间值 |
| `PeriodOfTime` | 表示一个时间段,包含开始和结束 |
| `PropertyValue` | 属性的基础值类型 |
| `UtcOffset` | UTC 偏移值(例如 `-05:00``+01:00` |
---
## 格式化输出
所有组件和属性都提供 `formatted()` 方法,返回符合 iCalendar 规范的字符串。`Calendar.formatted()` 方法生成完整的 `.ics` 输出,包含 `BEGIN:VCALENDAR`/`END:VCALENDAR`
```java
String ics = calendar.formatted();
// BEGIN:VCALENDAR
// CALSCALE:GREGORIAN
// METHOD:PUBLISH
// ...
// END:VCALENDAR
```
@@ -0,0 +1,102 @@
---
title: Calendar Toolbox
---
import { Tabs, Tab } from "@rspress/core/theme"
## 介绍
Calendar Toolbox 是一个 Java 库,旨在简化遵循 iCalendar 规范(RFC 5545)的 `.ics` 文件的创建。该库为开发者提供了简洁的 API,可生成能够导入到 Microsoft Outlook、Google Calendar 和 Apple Calendar 等主流日历应用程序中的日历事件。
通过 Calendar Toolbox,您可以以编程方式轻松创建、定制和导出日历事件文件,从而以最少的代价将日历功能集成到您的 Java 应用中。
## 特性
- **完整 RFC 5545 兼容** — 支持 VEVENT、VTODO、VJOURNAL、VFREEBUSY、VTIMEZONE 和 VALARM 等标准 iCalendar 组件。
- **流式 Builder 模式** — 所有组件和属性均使用 Builder 模式,构建过程可读性强且直观。
- **类型安全属性** — 强类型的属性和参数确保编译期正确性。
- **自定义扩展** — 支持日历级和组件级的自定义 `X-` 属性。
- **轻量级** — 核心功能零外部依赖。
## 安装
<Tabs>
<Tab label="Gradle with Kotlin DSL">
```kotlin title="build.gradle.kts"
dependencies {
implementation("com.onixbyte:calendar-toolbox:1.1.0")
}
```
</Tab>
<Tab label="Maven">
```xml title="pom.xml"
<dependencies>
<dependency>
<groupId>com.onixbyte</groupId>
<artifactId>calendar-toolbox</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
```
</Tab>
</Tabs>
## 快速开始
```java
import com.onixbyte.calendar.Calendar;
import com.onixbyte.calendar.component.Event;
import com.onixbyte.calendar.component.property.*;
import com.onixbyte.calendar.property.*;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
public class CalendarExample {
public static void main(String[] args) {
// 创建所需的日期时间属性
var now = ZonedDateTime.now(ZoneOffset.UTC);
var dtstamp = DateTimeStamp.of(now);
var uid = UniqueIdentifier.of("meeting-001@example.com");
var dtstart = DateTimeStart.of(
LocalDateTime.of(2025, 8, 15, 9, 0),
"America/New_York"
);
var dtend = DateTimeEnd.of(
LocalDateTime.of(2025, 8, 15, 10, 0),
"America/New_York"
);
var summary = Summary.of("Team Standup");
var description = Description.of("Daily team standup meeting.");
// 构建事件
var event = Event.builder()
.withDateTimeStamp(dtstamp)
.withUniqueIdentifier(uid)
.withDateTimeStart(dtstart)
.withDateTimeEnd(dtend)
.withSummary(summary)
.withDescription(description)
.build();
// 构建日历并输出 .ics 内容
var calendar = Calendar.builder()
.withCalendarScale(CalendarScale.of("GREGORIAN"))
.withMethod(Method.of("PUBLISH"))
.withProductIdentifier(ProductIdentifier.of("-//OnixByte//Calendar Toolbox//EN"))
.withVersion(Version.of("2.0"))
.withComponents(event)
.build();
System.out.println(calendar.formatted());
}
}
```
上述代码会生成一个 `.ics` 格式的字符串,可以保存为文件或通过邮件发送。
## 许可证
Calendar Toolbox 是采用 MIT 许可证发布的开源软件。
+248
View File
@@ -0,0 +1,248 @@
---
title: Captcha API
---
## 包结构概览
库的代码组织在基础包 `com.onixbyte.captcha` 下,结构如下:
| 包 | 描述 |
|---|---|
| `com.onixbyte.captcha` | 核心接口 |
| `com.onixbyte.captcha.impl` | 默认实现 |
| `com.onixbyte.captcha.text` | 文本生成器和渲染器接口 |
| `com.onixbyte.captcha.text.impl` | 文本生成器和渲染器实现 |
| `com.onixbyte.captcha.text.enums` | 文本相关枚举 |
| `com.onixbyte.captcha.background` | 背景生成器接口 |
| `com.onixbyte.captcha.background.impl` | 背景生成器实现 |
| `com.onixbyte.captcha.noise` | 噪点生成器接口 |
| `com.onixbyte.captcha.noise.impl` | 噪点生成器实现 |
| `com.onixbyte.captcha.gimpy` | 扭曲引擎接口 |
| `com.onixbyte.captcha.gimpy.impl` | 扭曲引擎实现 |
---
## Producer
负责创建 CAPTCHA 图片并在其上绘制文字的顶层接口。
```java
Producer captcha = DefaultCaptchaProducer.builder()
.textProducer(textProducer)
.wordRenderer(wordRenderer)
.gimpyEngine(gimpyEngine)
.backgroundProducer(backgroundProducer)
.width(200)
.height(50)
.borderDrawn(true)
.borderColour(Color.BLACK)
.borderThickness(1)
.build();
String text = captcha.createText();
BufferedImage image = captcha.createImage(text);
```
### DefaultCaptchaProducer Builder
| 方法 | 默认值 | 描述 |
|---|---|---|
| `textProducer` | `DefaultTextProducer.builder().build()` | 文本生成器 |
| `wordRenderer` | `DefaultWordRenderer.builder().build()` | 文字渲染器 |
| `gimpyEngine` | `WaterRipple.builder().build()` | 扭曲引擎 |
| `backgroundProducer` | `DefaultBackgroundProducer.builder().build()` | 背景生成器 |
| `width` | `200` | 验证码图片宽度 |
| `height` | `50` | 验证码图片高度 |
| `borderDrawn` | `true` | 是否绘制边框 |
| `borderColour` | `Color.BLACK` | 边框颜色 |
| `borderThickness` | `1` | 边框厚度 |
---
## Text
### TextProducer
用于创建 CAPTCHA 文本字符串的接口。
```java
public interface TextProducer {
String getText();
}
```
#### DefaultTextProducer
生成可配置长度和字符集的随机文本。
```java
DefaultTextProducer textProducer = DefaultTextProducer.builder()
.length(6) // 默认: 6
.chars("ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray()) // 默认: a-z, A-Z, 0-9
.build();
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| `length` | `6` | 生成文本的长度 |
| `chars` | `a-z``A-Z``0-9`(共 62 个字符) | 生成文本使用的字符集 |
### WordRenderer
将文字渲染到图片上的接口。
```java
public interface WordRenderer {
BufferedImage renderWord(String word, int width, int height);
}
```
#### DefaultWordRenderer
使用可配置的字体、颜色和间距渲染文字。
```java
DefaultWordRenderer wordRenderer = DefaultWordRenderer.builder()
.fontSize(40) // 默认: 40
.fonts("Arial", "Courier") // 默认: Arial, Courier
.fontColour(Color.BLACK) // 默认: Color.BLACK
.charSpace(2) // 默认: 2
.fontStyle(FontStyle.BOLD) // 默认: FontStyle.BOLD
.build();
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| `fontSize` | `40` | 字号(像素) |
| `fonts` | `["Arial", "Courier"]` | 字体族(随机选择) |
| `fontColour` | `Color.BLACK` | 字体颜色 |
| `charSpace` | `2` | 字符间距(像素) |
| `fontStyle` | `FontStyle.BOLD` | 字体样式 |
### FontStyle
定义 CAPTCHA 文字渲染支持的字体样式。
| 值 | 对应的 AWT 常量 | 描述 |
|---|---|---|
| `PLAIN` | `java.awt.Font.PLAIN` | 普通样式 |
| `BOLD` | `java.awt.Font.BOLD` | 粗体 |
| `ITALIC` | `java.awt.Font.ITALIC` | 斜体 |
| `BOLD_ITALIC` | `java.awt.Font.BOLD | Font.ITALIC` | 粗斜体 |
---
## GimpyEngine
用于对图片应用扭曲效果的接口。
```java
public interface GimpyEngine {
BufferedImage getDistortedImage(BufferedImage baseImage);
}
```
### WaterRipple
应用水波纹扭曲效果。继承 `AbstractGimpyEngine`,自动添加噪点。
```java
WaterRipple gimpy = WaterRipple.builder()
.noiseProducer(DefaultNoiseProducer.builder().build()) // 默认: DefaultNoiseProducer
.build();
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | 噪点生成器 |
### FishEyeGimpy
应用鱼眼扭曲效果,在图片上绘制水平和垂直线条。
```java
FishEyeGimpy gimpy = FishEyeGimpy.builder()
.build();
```
### ShadowGimpy
应用阴影和波纹效果。继承 `AbstractGimpyEngine`,自动添加噪点。
```java
ShadowGimpy gimpy = ShadowGimpy.builder()
.noiseProducer(DefaultNoiseProducer.builder().build()) // 默认: DefaultNoiseProducer
.build();
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| `noiseProducer` | `DefaultNoiseProducer.builder().build()` | 噪点生成器 |
---
## Noise
### NoiseProducer
向图片添加噪点的接口。
```java
public interface NoiseProducer {
void makeNoise(BufferedImage image, float factorOne, float factorTwo,
float factorThree, float factorFour);
}
```
#### DefaultNoiseProducer
使用可配置的颜色添加噪点曲线。
```java
DefaultNoiseProducer noise = DefaultNoiseProducer.builder()
.noiseColour(Color.BLACK) // 默认: Color.BLACK
.build();
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| `noiseColour` | `Color.BLACK` | 噪点颜色 |
#### NoNoiseProducer
不向图片添加任何噪点的空实现。
```java
NoiseProducer noise = NoNoiseProducer.builder()
.build();
```
---
## Background
### BackgroundProducer
向图片添加背景的接口。
```java
public interface BackgroundProducer {
BufferedImage addBackground(BufferedImage image);
}
```
#### DefaultBackgroundProducer
创建具有可配置起始和结束颜色的渐变背景。
```java
DefaultBackgroundProducer background = DefaultBackgroundProducer.builder()
.colourFrom(Color.WHITE) // 默认: Color.LIGHT_GRAY
.colourTo(Color.LIGHT_GRAY) // 默认: Color.WHITE
.build();
```
| 方法 | 默认值 | 描述 |
|---|---|---|
| `colourFrom` | `Color.LIGHT_GRAY` | 渐变起始颜色 |
| `colourTo` | `Color.WHITE` | 渐变结束颜色 |
+89
View File
@@ -0,0 +1,89 @@
---
title: Captcha
---
import { Tabs, Tab } from "@rspress/core/theme"
## 介绍
Captcha 是一个用于生成 CAPTCHA 验证码图片的 Java 库。本项目是 Google Kaptcha 的精神继承者,按照现代开发实践进行了现代化改造。
通过 Captcha,您可以轻松生成可定制的 CAPTCHA 图片,支持多种扭曲效果、噪点和背景选项,轻松集成到您的 Java 应用中。
## 特性
- **易于集成** — 基于 Builder 的简洁 API,快速完成配置和集成。
- **可定制的验证码生成** — 配置文本长度、字符集、字体样式和颜色。
- **多种扭曲效果** — 支持水波纹、鱼眼和阴影效果。
- **可配置噪点** — 使用自定义颜色添加噪点线条,或完全禁用噪点。
- **渐变背景** — 可自定义的渐变背景颜色。
- **简洁现代的代码** — 文档完善、类型安全且易于扩展。
## 安装
<Tabs>
<Tab label="Gradle with Kotlin DSL">
```kotlin title="build.gradle.kts"
dependencies {
implementation("com.onixbyte:captcha:1.0.0")
}
```
</Tab>
<Tab label="Maven">
```xml title="pom.xml"
<dependencies>
<dependency>
<groupId>com.onixbyte</groupId>
<artifactId>captcha</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
```
</Tab>
</Tabs>
## 快速开始
```java
import com.onixbyte.captcha.Producer;
import com.onixbyte.captcha.background.BackgroundProducer;
import com.onixbyte.captcha.background.impl.DefaultBackgroundProducer;
import com.onixbyte.captcha.gimpy.GimpyEngine;
import com.onixbyte.captcha.gimpy.impl.WaterRipple;
import com.onixbyte.captcha.impl.DefaultCaptchaProducer;
import com.onixbyte.captcha.noise.NoiseProducer;
import com.onixbyte.captcha.noise.impl.DefaultNoiseProducer;
import com.onixbyte.captcha.text.TextProducer;
import com.onixbyte.captcha.text.WordRenderer;
import com.onixbyte.captcha.text.impl.DefaultTextProducer;
import com.onixbyte.captcha.text.impl.DefaultWordRenderer;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class CaptchaExample {
public static void main(String[] args) throws IOException {
// 使用默认配置创建 CAPTCHA 生产者
Producer captcha = DefaultCaptchaProducer.builder().build();
// 生成文本并创建图片
String captchaText = captcha.createText();
BufferedImage captchaImage = captcha.createImage(captchaText);
// 保存图片到文件
ImageIO.write(captchaImage, "png", new File("captcha.png"));
System.out.println("CAPTCHA 文本: " + captchaText);
}
}
```
以上代码生成一张包含 6 位随机字符的 CAPTCHA 图片,并将其保存为 PNG 文件。
## 许可证
Captcha 是采用 MIT 许可证发布的开源软件。
@@ -0,0 +1,91 @@
---
title: Delta Force Guide API
---
## 后端 API 概览
后端是基于 Spring Boot 3 的应用程序,代码组织在基础包 `com.onixbyte.deltaforceguide` 下:
| 包 | 描述 |
|---|---|
| `controller` | REST API 端点控制器 |
| `service` | 业务逻辑层 |
| `repository` | MyBatis 数据访问层 |
| `domain` | JPA 实体与领域对象 |
| `config` | Spring 配置(安全、缓存等) |
| `properties` | 配置属性类 |
| `enumeration` | 枚举类型 |
| `shared` | 共享工具类 |
## API 端点
### 认证
| 方法 | 路径 | 描述 | 认证 |
|---|---|---|---|
| `POST` | `/api/auth/login` | 使用凭证登录 | 否 |
| `POST` | `/api/auth/refresh` | 刷新 access token | 否 |
| `GET` | `/api/auth/profile` | 获取当前用户信息 | 是 |
### 枪械
| 方法 | 路径 | 描述 |
|---|---|---|
| `GET` | `/api/firearms` | 枪械列表(分页,可按类型筛选) |
| `GET` | `/api/firearms/:id` | 按 ID 获取枪械详情 |
| `POST` | `/api/firearms` | 创建新枪械 |
| `PUT` | `/api/firearms/:id` | 更新枪械信息 |
| `DELETE` | `/api/firearms/:id` | 删除枪械 |
### 改装
| 方法 | 路径 | 描述 |
|---|---|---|
| `GET` | `/api/modifications` | 改装列表(分页,可按枪械和标签筛选) |
| `GET` | `/api/modifications/:id` | 按 ID 获取改装详情 |
| `POST` | `/api/modifications` | 创建改装 |
| `POST` | `/api/modifications/batch` | 批量创建改装 |
| `PUT` | `/api/modifications/:id` | 更新改装 |
| `DELETE` | `/api/modifications/:id` | 删除改装 |
| `DELETE` | `/api/modifications/batch-delete` | 批量删除改装 |
### 标签
| 方法 | 路径 | 描述 |
|---|---|---|
| `GET` | `/api/tags` | 获取所有标签 |
## 前端路由
| 路径 | 布局 | 页面 | 描述 |
|---|---|---|---|
| `/` | 主布局 | 枪械浏览 | 首页 — 枪械列表 |
| `/firearms` | 主布局 | 枪械浏览 | 枪械详情与搜索 |
| `/mod-codes` | 主布局 | 改装代码 | 改装代码库 |
| `/legal` | 主布局 | 法律信息 | 法律与隐私信息 |
| `/login` | 空白布局 | 登录 | 用户认证页面 |
## 前端状态管理
Redux Toolkit 结合 Redux Persist 管理以下状态:
- **认证状态** — Access token、refresh token、用户信息
- **设置状态** — 用户偏好,持久化至本地存储
## API 客户端
前端使用基于 Axios 封装的共享 `WebClient`,提供以下能力:
- 基础 URL 配置(指向后端 API)
- 通过请求拦截器自动注入 JWT access token
- 在收到 401 响应时自动刷新 token
## 基础设施
| 组件 | 技术 |
|---|---|
| 数据库 | PostgreSQL(使用 Flyway 进行数据库迁移) |
| 缓存 | Redis(会话和 token 存储) |
| 文件存储 | AWS S3(枪械图片) |
| 容器化 | Docker |
| 部署 | Docker Compose + Nginx |
@@ -0,0 +1,48 @@
---
title: Delta Force Guide
---
import { Tabs, Tab } from "@rspress/core/theme"
## 介绍
Delta Force Guide 是一个全栈 Web 应用,为游戏 Delta Force(三角洲部队)提供可搜索的枪械改装代码库。项目包含两个组件:
- **Web 前端** — 基于 React 的单页应用,用于浏览、筛选和复制改装代码。
- **后端服务** — 基于 Spring Boot 的 REST API,处理数据持久化、身份认证和内容管理。
线上站点位于 **[dfguide.onixbyte.cn](https://dfguide.onixbyte.cn)**。
## 特性
- **枪械浏览** — 浏览精选的游戏内枪械列表及详细属性。
- **改装代码库** — 按武器、模式和标签搜索筛选改装代码。
- **一键复制** — 直接从界面复制改装代码。
- **高效渲染** — 通过窗口虚拟化实现大列表的流畅渲染。
- **身份认证** — 支持用户登录,采用 JWT 认证和验证码校验。
- **后台管理** — 枪械与改装数据完整的增删改查功能。
- **静态友好** — 前端以静态站点部署,通过 API 代理与后端通信。
## 架构
| 组件 | 技术栈 |
|---|---|
| **前端** | 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 |
| **认证** | JWTaccess 和 refresh token)、验证码集成 |
| **存储** | AWS S3(图片上传) |
前端是由 Vite 构建的静态站点,通过 API 与 Spring Boot 后端通信。认证采用 JWT access 和 refresh token 机制,refresh token 通过 Redis 管理。
## 代码仓库
- [delta-force-guide-server](https://github.com/onixbyte/delta-force-guide-server) — Spring Boot 后端
- [delta-force-guide-web](https://github.com/onixbyte/delta-force-guide-web) — React 前端
## 快速链接
- **线上站点:** [dfguide.onixbyte.cn](https://dfguide.onixbyte.cn)
## 许可证
Delta Force Guide 是采用 MIT 许可证发布的开源软件。
+71
View File
@@ -0,0 +1,71 @@
---
title: Helix
---
## 介绍
Helix 是一个全栈企业级应用模板,旨在加速生产级业务应用的开发。它提供了预构建的基础,包含企业应用所需的全部基本功能,使团队能够专注于业务逻辑而非基础设施。
项目由两个组件构成:
- **Helix Server** — 基于 Spring Boot 的后端,提供 REST API、身份认证、权限管理和数据管理。
- **Helix Web** — 基于 React 的单页应用前端,具备现代化的 UI、基于角色的路由和企业级身份集成。
Helix 旨在作为项目的起点使用。Fork 或克隆它,然后在现成的基础上开始构建您自己的业务功能。
## 特性
### 后端(Helix Server
- **身份认证与授权** — 基于 JWT 的 access token 和 refresh token 流程,配合 Spring Security。支持 Microsoft Entra IDAzure AD)集成。
- **基于角色的访问控制** — 通过角色、权限和菜单级访问控制实现细粒度权限管理。
- **用户与组织管理** — 用户、部门、职位和角色的完整增删改查。
- **菜单管理** — 层级菜单树,支持按角色配置可见性。
- **资产管理** — 文件上传至 AWS S3,支持 CDN 前缀处理。
- **设置管理** — 类型化的应用配置项持久化至数据库。
- **验证码集成** — 登录和注册流程中的图形验证码校验。
- **Redis 缓存** — 高性能缓存,支持可配置 TTL 和自定义序列化器。
- **数据访问** — Spring Data JPA 与 MyBatis 混合持久化方案。
- **校验** — Bean Validation 分组校验与自定义校验约束。
### 前端(Helix Web
- **企业级身份认证** — 通过 MSAL 实现 Microsoft Entra ID 登录。可扩展的社交登录提供商架构(Microsoft、Google、GitLab、Slack、Discord、钉钉、飞书、企业微信、邮箱/密码)。
- **仪表盘布局** — 响应式管理后台,可折叠侧边栏,基于角色的菜单渲染。
- **用户管理** — 数据表格支持搜索、分页,添加/编辑对话框,角色分配和手机号校验。
- **角色与菜单管理** — 角色增删改查与权限分配。基于树形的菜单配置。
- **部门与职位** — 组织层级管理界面。
- **路由保护** — 在页面加载前检查认证和授权状态。
- **状态管理** — Redux Toolkit 配合 Redux Persist 实现认证 token 的持久化。
- **HTTP 客户端** — 基于 Axios 封装的请求客户端,自动注入 JWT token 并在 401 时自动刷新。
## 架构
| 层 | 技术栈 |
|---|---|
| **前端** | React 19、TypeScript、Tailwind CSS 4、Ant Design 6、React Router 7、Redux Toolkit、Axios、MSAL |
| **后端** | Spring Boot 3.5、Java 17、Spring Security、MyBatis、Spring Data JPA |
| **数据库** | PostgreSQL(使用 Flyway 迁移) |
| **缓存** | Redis(会话和 token 存储) |
| **存储** | AWS S3(资源上传) |
前端通过 RESTful JSON API 与后端通信。认证流程使用短有效期的 JWT access tokenrefresh token 存储在 Redis 中。Microsoft Entra ID 集成在前端通过 MSAL 处理,并在后端进行校验。
## 代码仓库
- [helix-server](https://git.onixbyte.cn/helix/helix-server) — Spring Boot 后端
- [helix-web](https://git.onixbyte.cn/helix/helix-web) — React 前端
## 快速开始
Helix 是一个模板项目。启动新项目的步骤:
1. Fork 或克隆 `helix-server` 和 `helix-web` 两个仓库。
2. 在后端配置您的数据库、Redis 和 S3 设置。
3. 在前端配置您的认证提供商和 API 基础地址。
4. 启动后端:`./gradlew bootRun`
5. 启动前端:`pnpm install && pnpm dev`
## 许可证
Helix 是采用 MIT 许可证发布的开源软件。
+21
View File
@@ -0,0 +1,21 @@
---
title: 项目
---
探索由 OnixByte 开发的开源项目。
## 库和工具包
- **[OnixByte Toolbox](/projects/onixbyte-toolbox)** — 面向 Java 应用的开发工具包:AES、哈希、Base64、集合工具、密钥加载器、统计计算器、标识符生成器和泛型元组。
- **[regions4j](/projects/regions4j)** — 基于 ISO 3166-1 的类型安全 Java 枚举地区元数据,支持 O(1) 查找、E.164 拨号前缀和区域标签。
- **[Captcha](/projects/captcha)** — 现代化的 Java 验证码生成库,支持水波纹、鱼眼和阴影扭曲效果。
- **[Calendar Toolbox](/projects/calendar-toolbox)** — 遵循 iCalendar 规范(RFC 5545)创建 `.ics` 文件的 Java 库。
## 全栈应用
- **[Helix](/projects/helix)** — 企业级应用模板,后端使用 Spring Boot,前端使用 React,集成 JWT 认证、RBAC 权限管理、用户与组织管理以及 Microsoft Entra ID 集成。
- **[Delta Force Guide](/projects/delta-force-guide)** — 为游戏《三角洲行动》提供可搜索枪械改装代码库的 Web 应用,包含 React 单页应用和 Spring Boot REST API。
## Vite 插件
- **[Port Checker](/projects/vite-plugins/port-checker)** — 当 Vite 开发服务器监听浏览器限制的端口时发出警告,避免无响应的连接失败。
@@ -0,0 +1,209 @@
---
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` |
| Tuple | `tuple` | `com.onixbyte.tuple` |
| Identity Generator | `identity-generator` | `com.onixbyte.identitygenerator` |
---
## Common Toolbox
### 适配器
`ObjectMapAdapter` — 对象与 Map 之间的转换器。适用于需要键值表示的场景,如序列化或数据转换。
```java
import com.onixbyte.common.adapter.ObjectMapAdapter;
```
### 工具类
| 类 | 描述 |
|---|---|
| `AesUtil` | AES 对称加密/解密,支持密钥生成 |
| `Base64Util` | Base64 编解码,支持多种字符集 |
| `BoolUtil` | 布尔值解析与转换工具 |
| `BranchUtil` | 条件分支辅助,支持函数式链式调用 |
| `CollectionUtil` | 集合操作 — 分组、分区、合并 |
| `HashUtil` | 哈希工具,支持 MD5、SHA-1、SHA-256、SHA-512 |
| `MapUtil` | Map 构建、合并和转换辅助 |
| `RangeUtil` | 数值范围操作,支持边界处理 |
**AesUtil 示例:**
```java
var key = AesUtil.generateKey();
var encrypted = AesUtil.encrypt("hello world", key);
var decrypted = AesUtil.decrypt(encrypted, key);
```
**HashUtil 示例:**
```java
var md5 = HashUtil.md5("hello world");
var sha256 = HashUtil.sha256("hello world");
var fileSha = HashUtil.sha256(new File("data.bin"));
```
**CollectionUtil 示例:**
```java
var partitioned = CollectionUtil.partition(list, 100);
var grouped = CollectionUtil.groupBy(users, User::getDepartment);
```
---
## Crypto Toolbox
提供了加载 PEM 格式密钥的简洁抽象。支持 RSA 和 ECDSA 算法。
### 密钥加载器
| 类 | 描述 |
|---|---|
| `RSAPrivateKeyLoader` | 从 PEM 字符串加载 RSA 私钥 |
| `RSAPublicKeyLoader` | 从 PEM 字符串加载 RSA 公钥 |
| `ECPrivateKeyLoader` | 从 PEM 字符串加载 ECDSA 私钥 |
| `ECPublicKeyLoader` | 从 PEM 字符串加载 ECDSA 公钥 |
所有密钥加载器实现 `PrivateKeyLoader``PublicKeyLoader` 接口。
**RSA 示例:**
```java
var privateKey = new RSAPrivateKeyLoader().load(pemString);
var publicKey = new RSAPublicKeyLoader().load(pemString);
```
**ECDSA 示例:**
```java
var ecPrivateKey = new ECPrivateKeyLoader().load(pemString);
var ecPublicKey = new ECPublicKeyLoader().load(pemString);
```
### 工具类
`CryptoUtil` — 提供便捷的数字签名生成和验证方法,以及通用密码学辅助功能。
### 异常
| 类 | 描述 |
|---|---|
| `KeyLoadingException` | PEM 格式密钥解析失败时抛出 |
---
## Math Toolbox
用于处理数值数据集的统计计算工具。
### 核心类
| 类 | 描述 |
|---|---|
| `Calculator` | 统计计算器 — 均值、中位数、方差、标准差、总和、最小值、最大值 |
| `PercentileCalculator` | 百分位数计算器,支持可配置的插值策略 |
**Calculator 示例:**
```java
var stats = new Calculator(Arrays.asList(1.0, 2.0, 3.0, 4.0, 5.0));
double mean = stats.getMean();
double median = stats.getMedian();
double stdDev = stats.getStandardDeviation();
```
**PercentileCalculator 示例:**
```java
var calculator = new PercentileCalculator(data);
double p95 = calculator.calculate(95);
double p99 = calculator.calculate(99);
```
### 数据模型
| 类 | 描述 |
|---|---|
| `QuartileBounds` | 包含 Q1、中位数(Q2)、Q3 值及 IQR 和须线边界 |
---
## Tuple
轻量级泛型元组类型,适用于需要返回多个值但无需定义专用类的场景。
### 类
| 类 | 类型参数 | 可变性 |
|---|---|---|
| `Tuple<A, B>` | 两个元素 | 可变 |
| `ImmutableTuple<A, B>` | 两个元素 | 不可变 |
| `Triple<A, B, C>` | 三个元素 | 可变 |
| `ImmutableTriple<A, B, C>` | 三个元素 | 不可变 |
**示例:**
```java
var pair = Tuple.of("key", 42);
var triple = Triple.of("id", "name", 100);
var immutable = ImmutableTuple.of("constant", true);
// 访问器
String first = pair.getFirst();
Integer second = pair.getSecond();
// 三元组访问器
String a = triple.getFirst();
String b = triple.getSecond();
Integer c = triple.getThird();
```
---
## Identity Generator
生成适用于数据库主键或分布式 ID 的唯一标识符。
### 接口
`IdentityGenerator<T>` — 生成类型为 `T` 的标识符。
### 实现
| 类 | 描述 |
|---|---|
| `SequentialUuidGenerator` | 生成时间排序的顺序 UUID(优化数据库索引性能) |
| `SnowflakeIdentityGenerator` | 雪花算法分布式唯一 ID 生成 |
**顺序 UUID**
```java
var generator = new SequentialUuidGenerator();
UUID id = generator.nextId(); // 时间排序 UUID,对 B-tree 友好
```
**雪花:**
```java
var generator = new SnowflakeIdentityGenerator(workerId, datacenterId);
long id = generator.nextId(); // 64 位雪花 ID
```
### 异常
| 类 | 描述 |
|---|---|
| `TimingException` | 系统时钟回拨时抛出,保证 ID 唯一性不受影响 |
@@ -0,0 +1,54 @@
---
title: OnixByte Toolbox
---
import { Tabs, Tab } from "@rspress/core/theme"
## 介绍
OnixByte Toolbox 是一个面向 Java 应用的开发工具包,提供了一系列便捷、可复用的工具,帮助开发者高效编写代码。它由 OnixByte 设计和维护,采用 monorepo 架构,包含多个专用库,每个库解决一个特定的开发需求 — 从通用工具类和密码学,到数学计算和标识符生成。
该工具包已发布到 Maven Central,使用 `com.onixbyte` 作为 group ID。每个模块独立版本管理,可在任何 Java 17+ 项目中使用。
## 模块
| 模块 | Artifact ID | 描述 |
|--------------------|----------------------|-----------------------------------|
| Common Toolbox | `common-toolbox` | 日常工具类 — AES 加密、哈希、Base64、集合、分支、范围 |
| Crypto Toolbox | `crypto-toolbox` | RSA 和 ECDSA 算法的公私钥加载 |
| Math Toolbox | `math-toolbox` | 统计计算、百分位数分析、四分位数计算 |
| Tuple | `tuple` | 泛型二元组和三元组,含不可变版本 |
| Identity Generator | `identity-generator` | 雪花算法和顺序 UUID 唯一标识符生成 |
| Version Catalogue | `version-catalogue` | OnixByte 项目的集中式 Gradle 版本目录 |
## 安装
在构建配置中添加所需模块的依赖:
<Tabs>
<Tab label="Gradle with Kotlin DSL">
```kotlin title="build.gradle.kts"
dependencies {
implementation("com.onixbyte:$artefactId:$version")
}
```
</Tab>
<Tab label="Maven">
```xml title="pom.xml"
<dependency>
<groupId>com.onixbyte</groupId>
<artifactId>${artefactId}</artifactId>
<version>${version}</version>
</dependency>
```
</Tab>
</Tabs>
## 要求
- Java 17 或更高版本
## 许可证
OnixByte Toolbox 是采用 MIT 许可证发布的开源软件。
+104
View File
@@ -0,0 +1,104 @@
---
title: Regions for Java
---
import { Tabs, Tab } from "@rspress/core/theme"
## 介绍
**regions4j** 是一个轻量级、类型安全的 Java 库,基于 ISO 3166-1 标准提供全面的世界地区元数据。它旨在简化 Java 企业应用中的国际化(i18n)、电信路由和地区数据管理工作。
该库将每个 ISO 3166-1 国家和地区建模为枚举常量,使您在引用地区时获得编译期安全性和 IDE 自动补全支持。凭借内置的 O(1) 查找、零外部依赖和 Java 8 兼容性,它适用于任何规模的项目 — 从微服务到整体式企业系统。
## 特性
- **ISO 3166-1 合规** — 完整支持所有已分配国家和地区的 Alpha-2`abbreviation`)和 Alpha-3`code`)格式。
- **电信元数据** — 包含每个地区的 E.164 国际拨号前缀。
- **区域支持** — 每个地区提供默认的区域标签(如 `zh_HK`、`en_US`、`en_GB` 等),辅助 i18n 工作流。
- **高性能** — 线程安全、不可变的内部哈希映射提供常量时间的缩写或代码查找。
- **零依赖** — 纯 Java 库,无任何外部依赖。
- **日历化版本管理** — 版本号采用 `YYYY.MM` 格式(如 `2025.12`),以透明地反映底层 ISO 数据的新鲜度,而非语义化版本号。
## 核心数据模型
每个地区暴露四个属性:
| 属性 | 类型 | 描述 | 示例 |
|---|---|---|---|
| `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` |
| `locale` | String | 默认语言和地区标签 | `zh_HK`、`en_US`、`en_GB`、`ru_RU` |
## 安装
<Tabs>
<Tab label="Gradle with Kotlin DSL">
```kotlin title="build.gradle.kts"
dependencies {
implementation("com.onixbyte:regions4j:$version")
}
```
</Tab>
<Tab label="Maven">
```xml title="pom.xml"
<dependency>
<groupId>com.onixbyte</groupId>
<artifactId>regions4j</artifactId>
<version>${version}</version>
</dependency>
```
</Tab>
</Tabs>
> **版本说明:** 该库使用日历化版本管理(`YYYY.MM`)而非语义化版本号。版本字符串如 `2025.12` 可以直观地告诉您地区数据反映的是 2025 年 12 月的 ISO 3166-1 状态。
## 使用
### 直接访问
通过枚举常量直接引用任何地区:
```java
Region uk = Region.UNITED_KINGDOM;
uk.getAbbreviation(); // "GB"
uk.getCode(); // "GBR"
uk.getDialCode(); // "44"
uk.getLocale(); // "en_GB"
```
### 高效查找
从字符串输入中查找地区 — 非常适合处理 Web 请求、API 负载或数据库记录:
```java
// 按 Alpha-2 缩写查找(区分大小写)
Region region = Region.fromAbbreviation("HK");
// 按 Alpha-3 代码查找(不区分大小写)
Region region = Region.fromCode("HKG");
```
### Java Locale 集成
将地区的 locale 字符串转换为 `java.util.Locale` 以配合标准 Java i18n API 使用:
```java
Region region = Region.CHINA;
Locale javaLocale = Locale.forLanguageTag(region.getLocale().replace("_", "-"));
javaLocale.getDisplayCountry(Locale.UK); // "China"
```
## 性能
首次访问时,库会将所有地区初始化到不可变的 `HashMap` 结构中。后续通过 `fromAbbreviation()` 和 `fromCode()` 进行的查找均为线程安全且以常量时间运行 — 适用于高吞吐量的请求路径。
## 要求
- Java 8 或更高版本
## 许可证
regions4j 是采用 MIT 许可证发布的开源软件。
@@ -0,0 +1,11 @@
---
title: Vite 插件
---
## 概览
由 OnixByte 开发和维护的 Vite 插件合集。每个插件旨在解决 Vite 开发工作流中的特定问题 — 轻量级、零依赖、即插即用。
## 可用插件
- **[Port Checker](/projects/vite-plugins/port-checker)** — 当开发服务器监听浏览器限制的端口(依据 Fetch 规范)时发出警告,帮助您避免无响应的连接失败。
@@ -0,0 +1,67 @@
---
title: Port Checker
---
import { Tabs, Tab } from "@rspress/core/theme"
## 介绍
**vite-plugin-port-checker** 是一个轻量级的 Vite 插件,可在开发服务器监听被常见浏览器屏蔽的端口时发出警告。Chrome 和 Firefox 等浏览器维护了一份[受限制端口列表](https://fetch.spec.whatwg.org/#port-blocking) — 这些端口通常与 SMTP、SSH 和 DNS 等知名协议关联 — 并拒绝连接这些端口。如果不小心将开发服务器运行在这些端口上,会导致令人困惑的"连接被拒绝"或"已被屏蔽"错误,且没有任何明确的解释。
该插件会在启动时检测到这种情况,并向控制台打印一条清晰且带有颜色标记的警告,建议您修改 Vite 配置中的 `server.port` 设置。
## 特性
- **自动检测** — 对照完整的 Fetch 规范端口屏蔽列表(68 个受限端口)检查开发服务器端口。
- **清晰的警告** — 黄色高亮控制台输出,并提供可操作的指导。
- **零配置** — 开箱即用,无需设置任何选项。
- **轻量级** — 单文件插件,除 Vite 本身外无任何依赖。
## 安装
<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>
</Tabs>
## 使用
在 `vite.config.ts` 中添加插件:
```ts title="vite.config.ts"
import { defineConfig } from "vite"
import checkRestrictedPort from "vite-plugin-port-checker"
export default defineConfig({
plugins: [checkRestrictedPort()],
})
```
当开发服务器启动在受限端口(如 25、22 或 53 端口)时,您将看到:
```
[Warning] The current listening port 25 is categorised as a restricted port
by most browsers. This may prevent you from accessing the application.
Please consider changing the port in your 'vite.config.ts' or 'vite.config.js'
via 'server.port'.
```
## 工作原理
该插件通过钩入 Vite 的 `configureServer` 生命周期工作。当 HTTP 服务器触发 `listening` 事件后,插件检查绑定的端口号,并与 [Fetch 规范](https://fetch.spec.whatwg.org/#port-blocking)中定义的 68 个受限端口进行比对。如果匹配,则通过黄色的 `console.warn` 消息提醒开发者。
## 要求
- Vite 3.0.0 或更高版本
## 许可证
vite-plugin-port-checker 是采用 MIT 许可证发布的开源软件。
+1 -1
View File
@@ -112,7 +112,7 @@
"zh-hans": "折叠"
},
"blogs": {
"en-gb": "Blogs",
"en-gb": "Blog",
"zh-hans": "博客"
},
"notifications": {
+60
View File
@@ -0,0 +1,60 @@
import type { HTMLAttributes } from "react"
const macOSSymbols: Record<string, string> = {
cmd: "⌘",
command: "⌘",
opt: "⌥",
option: "⌥",
alt: "⌥",
ctrl: "⌃",
control: "⌃",
shift: "⇧",
enter: "↩",
return: "↩",
tab: "⇥",
esc: "⎋",
escape: "⎋",
delete: "⌫",
backspace: "⌫",
forwardDelete: "⌦",
up: "↑",
down: "↓",
left: "←",
right: "→",
space: "␣",
fn: "Fn",
globe: "🌐",
eject: "⏏",
power: "⏻",
capslock: "⇪",
home: "↖",
end: "↘",
pageup: "⇞",
pagedown: "⇟",
clear: "⌧",
}
export interface KbdProps extends HTMLAttributes<HTMLElement> {
mac?: keyof typeof macOSSymbols
}
export function Kbd({ children, mac, className = "", ...rest }: KbdProps) {
const label = children ?? (mac ? macOSSymbols[mac] : null)
if (!label) return null
return (
<kbd
className={`inline-flex items-center justify-center min-w-[1.6em] px-1.5 py-0
text-[0.85em] leading-normal font-mono
rounded-md border border-b-2
border-gray-300 dark:border-gray-600
bg-gray-50 dark:bg-gray-800
text-gray-700 dark:text-gray-300
shadow-[0_1px_1px_rgba(0,0,0,0.075)]
align-baseline
${className}`.replace(/\s+/g, " ")}
{...rest}>
{label}
</kbd>
)
}
+1
View File
@@ -26,3 +26,4 @@ function DocLayout(props: DocLayoutProps) {
export * from "@rspress/core/theme-original"
export { DocLayout }
export { Kbd } from "./components/Kbd"
+17
View File
@@ -0,0 +1,17 @@
{
"outputDirectory": "doc_build",
"redirects": [
{
"source": "/:path(.*)",
"has": [
{
"type": "header",
"key": "x-vercel-ip-country",
"value": "CN"
}
],
"destination": "https://onixbyte.cn/:path*",
"permanent": false
}
]
}