refactor: rename projects to opensource-projects
Frees /products/ for the product page and makes the open-source archive explicit, rather than leaving two sections that both look like "projects". - Move the directory in both locales and update the 18 internal links pointing into it. - Rework helix for the GitHub layout: server/ and web/ are directories in a single repository there, not the two separate repositories Gitea had. The "fork both repositories" step and the section wording follow. - Correct helix's stated Java version to 21, which is what the build actually targets.
This commit is contained in:
30 files changed
+75
-71
No files matched your search
@@ -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,216 @@
|
||||
---
|
||||
title: Claude Code Skills Manager
|
||||
---
|
||||
|
||||
import { Tabs, Tab } from "@rspress/core/theme"
|
||||
|
||||
## Introduction
|
||||
|
||||
Claude Code Skills Manager (`ccsm`) is a CLI tool for discovering, installing, and managing Claude Code skills from Git-based marketplace repositories. It lets you register any public Git repository that exposes a `skills.json` manifest as a skill source, then search, install, update, and remove skills through a single command-line interface.
|
||||
|
||||
Skills are deployed directly into Claude Code's own skills directory (`~/.claude/skills/`), where Claude Code picks them up automatically at startup.
|
||||
|
||||
## Installation
|
||||
|
||||
<Tabs>
|
||||
<Tab label="Pre-built binaries">
|
||||
Download the latest binary for your platform from the [Releases page](https://onixbyte.dev/onixbyte/claude-code-skill-manager/releases).
|
||||
|
||||
| Platform | Binary |
|
||||
|----------|--------|
|
||||
| Linux (amd64) | `ccsm-linux-amd64` |
|
||||
| macOS (amd64) | `ccsm-darwin-amd64` |
|
||||
| Windows (amd64) | `ccsm-windows-amd64.exe` |
|
||||
|
||||
Place the binary somewhere on your `PATH` and rename it to `ccsm` (or `ccsm.exe` on Windows).
|
||||
</Tab>
|
||||
<Tab label="Cargo install">
|
||||
```bash
|
||||
git clone https://onixbyte.dev/onixbyte/claude-code-skill-manager.git
|
||||
cd claude-code-skill-manager
|
||||
cargo install --path .
|
||||
```
|
||||
Requires a Rust toolchain (install via [rustup.rs](https://rustup.rs)).
|
||||
</Tab>
|
||||
<Tab label="Build from source">
|
||||
```bash
|
||||
git clone https://onixbyte.dev/onixbyte/claude-code-skill-manager.git
|
||||
cd claude-code-skill-manager
|
||||
cargo build --release
|
||||
```
|
||||
The binary will be at `target/release/ccsm` (or `ccsm.exe` on Windows).
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Registering a marketplace
|
||||
|
||||
A marketplace is any public Git repository with a `skills.json` manifest at its root. Register one with:
|
||||
|
||||
```bash
|
||||
ccsm marketplace add https://github.com/example/skills
|
||||
```
|
||||
|
||||
CCSM fetches the manifest and caches it locally. You can register as many marketplaces as you need.
|
||||
|
||||
### Browsing and installing skills
|
||||
|
||||
```bash
|
||||
# Search across all registered marketplaces
|
||||
ccsm search
|
||||
|
||||
# Search with a keyword filter
|
||||
ccsm search git
|
||||
|
||||
# Install a skill by name
|
||||
ccsm install my-awesome-skill
|
||||
|
||||
# If the same name exists in multiple marketplaces, disambiguate
|
||||
ccsm install my-skill --marketplace my-marketplace
|
||||
```
|
||||
|
||||
### Managing installed skills
|
||||
|
||||
```bash
|
||||
# List installed skills
|
||||
ccsm list
|
||||
|
||||
# Show details about an installed skill
|
||||
ccsm info my-awesome-skill
|
||||
|
||||
# Update all installed skills to their latest versions
|
||||
ccsm update
|
||||
|
||||
# Update a specific skill
|
||||
ccsm update my-awesome-skill
|
||||
|
||||
# Remove a skill
|
||||
ccsm remove my-awesome-skill
|
||||
```
|
||||
|
||||
### Marketplace management
|
||||
|
||||
```bash
|
||||
# List all registered marketplaces
|
||||
ccsm marketplace list
|
||||
|
||||
# Refresh cached manifests (all marketplaces)
|
||||
ccsm marketplace update
|
||||
|
||||
# Refresh a specific marketplace
|
||||
ccsm marketplace update my-marketplace
|
||||
|
||||
# Remove a marketplace
|
||||
ccsm marketplace remove my-marketplace
|
||||
```
|
||||
|
||||
### Install modes
|
||||
|
||||
CCSM supports two deploy modes:
|
||||
|
||||
| Mode | Behaviour | Use case |
|
||||
|------|-----------|----------|
|
||||
| `copy` (default) | Files are physically copied to `~/.claude/skills/<name>/` | Normal use — safe and self-contained |
|
||||
| `link` | A symlink is created pointing to the local store | Skill development — changes to source files are picked up immediately |
|
||||
|
||||
Set the default mode in your config, or override per install:
|
||||
|
||||
```bash
|
||||
ccsm install my-skill --link
|
||||
```
|
||||
|
||||
## Creating Your Own Skill Marketplace
|
||||
|
||||
A marketplace is simply a public Git repository containing a `skills.json` manifest. There is no server component, no authentication, and no API key — CCSM reads the manifest directly from the Git forge's raw file endpoint.
|
||||
|
||||
### Marketplace repository structure
|
||||
|
||||
```
|
||||
your-marketplace-repo/
|
||||
skills.json # Required: the manifest
|
||||
README.md # Optional
|
||||
```
|
||||
|
||||
### The `skills.json` manifest
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "My Marketplace",
|
||||
"version": "1.0.0",
|
||||
"skills": [
|
||||
{
|
||||
"name": "my-skill",
|
||||
"description": "A short description shown in search results",
|
||||
"repository": "https://github.com/user/skill-repo",
|
||||
"branch": "main"
|
||||
},
|
||||
{
|
||||
"name": "another-skill",
|
||||
"description": "A skill that lives in a monorepo subdirectory",
|
||||
"repository": "https://github.com/user/monorepo",
|
||||
"branch": "main",
|
||||
"path": "skills/another-skill"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Top-level fields:**
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `name` | Yes | Marketplace display name |
|
||||
| `version` | No | Arbitrary version string for your own tracking |
|
||||
| `skills` | No | Array of skill entries (defaults to `[]`) |
|
||||
|
||||
**Skill entry fields:**
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `name` | Yes | Unique skill identifier (used with `ccsm install <name>`) |
|
||||
| `description` | Yes | One-line summary shown in `ccsm search` output |
|
||||
| `repository` | Yes | Public Git repository URL for the skill |
|
||||
| `branch` | No | Git branch to install from (tries `main` first, falls back to `master`) |
|
||||
| `path` | No | Subdirectory within the repository where the skill files live — enables monorepos hosting multiple skills |
|
||||
|
||||
### How it works
|
||||
|
||||
1. **Manifest fetching** — CCSM constructs a raw-file URL from the marketplace repository URL and fetches `skills.json` from either the `main` or `master` branch. This works with GitHub, Gitea, GitLab, and any Git forge that exposes raw file endpoints.
|
||||
|
||||
2. **Skill downloading** — When a user installs a skill, CCSM downloads the skill repository archive (ZIP or tar.gz) from the Git forge, extracts it, and deploys the files to `~/.claude/skills/<name>/`.
|
||||
|
||||
3. **Monorepo support** — If a skill entry specifies a `path`, CCSM navigates into that subdirectory after extraction before deploying, so a single repository can host multiple skills.
|
||||
|
||||
### What goes in a skill repository
|
||||
|
||||
Each skill repository is a standard Claude Code skill directory. At minimum it should contain a `SKILL.md` manifest file:
|
||||
|
||||
```
|
||||
my-skill-repo/
|
||||
SKILL.md # Claude Code skill manifest
|
||||
script.py # Supporting files
|
||||
templates/
|
||||
template.txt
|
||||
```
|
||||
|
||||
### Publishing steps
|
||||
|
||||
1. Create a **public** Git repository with a `skills.json` at the root, following the format above.
|
||||
2. Push it.
|
||||
3. Anyone can register it with `ccsm marketplace add <url>`.
|
||||
|
||||
## How CCSM Stores Data
|
||||
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `~/.claude/skills/` | Claude Code's skills directory — where skills are deployed |
|
||||
| `~/.config/ccsm/config.json` | CCSM configuration (registered marketplaces, default mode) |
|
||||
| `~/.config/ccsm/marketplaces/` | Cached marketplace manifests |
|
||||
| `~/.config/ccsm/skills/` | Downloaded skill files (local store) |
|
||||
|
||||
On Windows, `~/.config/` resolves to `C:\Users\<user>\AppData\Roaming\`.
|
||||
|
||||
## Licence
|
||||
|
||||
Claude Code Skills Manager is open-source software released under the MIT Licence.
|
||||
@@ -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,73 @@
|
||||
---
|
||||
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 21, 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 is a monorepo — both halves live in the same repository.
|
||||
|
||||
- [server/](https://github.com/onixbyte-opensource/helix/tree/main/server) — Spring Boot backend
|
||||
- [web/](https://github.com/onixbyte-opensource/helix/tree/main/web) — React frontend
|
||||
|
||||
## Getting Started
|
||||
|
||||
Helix is designed as a template project. To start a new project:
|
||||
|
||||
1. Fork or clone the [Helix repository](https://github.com/onixbyte-opensource/helix).
|
||||
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,25 @@
|
||||
---
|
||||
title: Open Source
|
||||
---
|
||||
|
||||
Open-source projects developed by OnixByte.
|
||||
|
||||
## Libraries & Toolkits
|
||||
|
||||
- **[OnixByte Toolbox](/opensource-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](/opensource-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](/opensource-projects/captcha)** — A modern Java CAPTCHA generation library with water ripple, fish-eye, and shadow distortion effects.
|
||||
- **[Calendar Toolbox](/opensource-projects/calendar-toolbox)** — A Java library for creating `.ics` files conforming to the iCalendar specification (RFC 5545).
|
||||
|
||||
## Full-Stack Applications
|
||||
|
||||
- **[Helix](/opensource-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](/opensource-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.
|
||||
|
||||
## Developer Tools
|
||||
|
||||
- **[Claude Code Skills Manager](/opensource-projects/claude-code-skill-manager)** — A CLI tool for discovering, installing, and managing Claude Code skills from Git-based marketplace repositories.
|
||||
|
||||
## Vite Plugins
|
||||
|
||||
- **[Port Checker](/opensource-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](/opensource-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.
|
||||
Reference in new issue
Block a user