Merge remote-tracking branch 'origin/main'
# Conflicts: # docs/en-gb/_nav.json # docs/zh-hans/_nav.json # i18n.json
This commit is contained in:
@@ -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,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.
|
||||
@@ -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 |
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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/",
|
||||
|
||||
@@ -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
|
||||
|
||||
表示 iCalendar(RFC 5545)VCALENDAR 容器的顶层对象。
|
||||
|
||||
```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` 定界符之间渲染。
|
||||
|
||||
### Event(VEVENT)
|
||||
|
||||
表示一个预定的活动/事件。
|
||||
|
||||
```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();
|
||||
```
|
||||
|
||||
### Todo(VTODO)
|
||||
|
||||
表示待办事项或任务。
|
||||
|
||||
```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();
|
||||
```
|
||||
|
||||
### Journal(VJOURNAL)
|
||||
|
||||
表示日记条目或笔记。
|
||||
|
||||
```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();
|
||||
```
|
||||
|
||||
### FreeBusy(VFREEBUSY)
|
||||
|
||||
表示空闲/忙碌时间信息。
|
||||
|
||||
```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();
|
||||
```
|
||||
|
||||
### TimeZone(VTIMEZONE)
|
||||
|
||||
定义时区规则,包括标准时间和夏令时转换。
|
||||
|
||||
```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();
|
||||
```
|
||||
|
||||
### Alarm(VALARM)
|
||||
|
||||
定义闹钟/提醒通知。支持三种闹钟类型:
|
||||
|
||||
```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 许可证发布的开源软件。
|
||||
@@ -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` | 渐变结束颜色 |
|
||||
@@ -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 |
|
||||
| **认证** | JWT(access 和 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 许可证发布的开源软件。
|
||||
@@ -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 ID(Azure 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 token,refresh 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 许可证发布的开源软件。
|
||||
@@ -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 许可证发布的开源软件。
|
||||
@@ -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 许可证发布的开源软件。
|
||||
Reference in New Issue
Block a user