mooncalguard

Pure MoonBit iCalendar parser, validator, recurrence, alarm, report, and diff toolkit.

icalendar
ics
calendar
rfc5545
validator
moon add WYT-ai-nb/mooncalguard@0.1.0
Download zip
Author
Version
0.1.0
License
MIT
Last updated
7 hours ago
Downloads
2
README

#MoonCalGuard

MoonCalGuard 是一个 MoonBit 原生 iCalendar / ICS 解析、校验、导出、重复规则分析、提醒校验、议程查询与事件差异检测库。它面向日历订阅、课程表、会议排期、自动化提醒和 CI 数据检查场景,把 .ics 文件从纯文本转换为结构化日历模型,并提供 RFC5545 常见规则校验。

#解决的问题

iCalendar 是日历交换的通用格式,但手写或脚本生成的 .ics 文件很容易出现折行、参数、时间格式、DTEND/DURATION 冲突、缺失 UID 等问题。MoonBit 生态目前缺少针对 ICS 的原生解析和校验工具。MoonCalGuard 让 MoonBit 项目可以在不依赖外部运行时的情况下检查、生成和比较日历数据。

#适用场景

  • 课程表、会议、活动报名系统导出 ICS;
  • CI 中校验仓库里的日程 fixture;
  • 日历订阅源发布前做格式体检;
  • 比较两个版本的日历事件变化;
  • 教学项目中展示文本协议解析、规则校验和规范化导出。

#安装

moon add WYT-ai-nb/mooncalguard

#最小使用示例

match @cal.parse_calendar(text) {
Ok(calendar) => {
let report = @cal.validate_calendar(calendar, @cal.ValidationOptions::strict())
println(@cal.render_validation(report))
}
Err(err) => println(err.message())
}

moon.pkg

import { "WYT-ai-nb/mooncalguard" @cal }

#本地验证

moon fmt --check moon check --deny-warn moon build moon test --deny-warn moon info moon run src/cmd/demo

src/cmd/demo 会解析项目内置的重复日程 fixture,输出校验报告、议程摘要和属性目录统计,适合作为验收 smoke test。

#API 与核心功能

  • parse_calendar(String):解析 ICS 文本为 Calendar
  • parse_content_line(String, Int):解析单行 content line;
  • validate_calendar(Calendar, ValidationOptions):执行规则校验;
  • ValidationOptions::strict():严格模式,适合发布前检查;
  • ValidationOptions::lenient():宽松模式,适合兼容外部订阅源;
  • render_calendar(Calendar):规范化导出 ICS;
  • render_validation(ValidationReport):输出 Markdown 风格报告;
  • diff_calendars(Calendar, Calendar):按 UID 比较事件新增、删除和修改;
  • render_diff(CalendarDiff):输出事件差异报告;
  • parse_recurrence_rule(String):解析 RRULE 重复规则;
  • parse_duration(String):解析 DURATION / TRIGGER 持续时间;
  • summarize_alarm(Component):提取 VALARM 行为、触发器和收件人信息;
  • collect_calendar_stats(Calendar):统计组件、属性、重复事件和提醒数量;
  • render_calendar_report(Calendar) / render_calendar_json(Calendar):输出 Markdown / JSON 风格诊断报告;
  • render_agenda(Calendar) / events_on_date(Calendar, String):生成议程和日期筛选结果;
  • render_property_catalog():输出内置属性目录;
  • fixture_*():自制测试数据,方便验收复现。

#支持范围

  • CRLF/LF 行切分;
  • RFC5545 折行展开;
  • content line、参数和值解析;
  • VCALENDAR、VEVENT、VTODO、VJOURNAL、VTIMEZONE 基础组件;
  • VEVENT/VTODO 内嵌 VALARM,VTIMEZONE 内嵌 STANDARD/DAYLIGHT;
  • VERSIONPRODIDUIDDTSTAMPDTSTARTDTENDDURATION 常见规则;
  • RRULE 常见字段:FREQ、INTERVAL、COUNT、UNTIL、WKST、BYDAY、BYMONTH、BYMONTHDAY、BYSETPOS;
  • VALARM 常见字段:ACTION、TRIGGER、DESCRIPTION、SUMMARY、ATTENDEE、REPEAT、DURATION;
  • UTC、TZID、本地 floating time 检查;
  • 文本转义与规范化导出;
  • 属性目录、字段归属、重复字段和未知字段诊断;
  • Markdown / JSON 风格报告与议程查询;
  • 基于 UID 的事件 diff。

#暂不支持范围

  • 不连接网络或读取系统日历;
  • 不完整展开无限或复杂 RRULE 实例序列;
  • 不完整实现时区数据库;
  • 不执行跨月精确时间运算;
  • 不发送真实提醒或邮件。

#Mooncakes 包名

WYT-ai-nb/mooncalguard

#项目材料

#发布前命令

moon fmt --check moon check --deny-warn moon build moon test --deny-warn moon info moon run src/cmd/demo moon login moon publish --dry-run

moon loginmoon publish --dry-run 会使用 Mooncakes 账号状态;如果正在切换 GitHub Desktop 或浏览器账号,可以先只运行前五条本地命令。

当前本地有效 MoonBit 代码统计约 5245 行(统计 src/**/*.mbt,排除空行和 // / /// 注释行),覆盖实现、测试和 demo。

#开源许可证与第三方参考

本项目采用 MIT 许可证。核心实现为原创 MoonBit 代码,没有移植第三方源码,没有使用来源不明素材。项目依据公开 iCalendar / RFC5545 格式规则设计解析和校验逻辑。

#
CalError

pub(all) suberror CalError {
EmptyInput
MissingColon(Int, String)
BadPropertyName(Int, String)
BadParameter(Int, String)
UnexpectedEnd(String)
MismatchedEnd(String, String)
NestedCalendar
MissingCalendar
MultipleCalendars
PropertyOutsideCalendar(String)
ComponentOutsideCalendar(String)
}

#
CalError::message

fn CalError::message(self : CalError) -> String

#
DurationError

pub(all) suberror DurationError {
EmptyDuration
MissingDurationPrefix
BadDurationNumber(String)
BadDurationDesignator(String)
MixedWeekAndDateTime
EmptyDurationBody
}

#
DurationError::message

fn DurationError::message(self : DurationError) -> String

#
RecurrenceError

pub(all) suberror RecurrenceError {
EmptyRule
MissingFrequency
DuplicatePart(String)
UnknownPart(String)
BadFrequency(String)
BadInteger(String)
BadWeekday(String)
BadUntil(String)
BadByDay(String)
ConflictingLimit
}

#
RecurrenceError::message

fn RecurrenceError::message(self : RecurrenceError) -> String

#
AlarmAction

pub(all) enum AlarmAction {
Audio
Display
Email
UnknownAction(String)
} derive(Eq,
Debug
)

#
AlarmAction::name

fn AlarmAction::name(self : AlarmAction) -> String

#
AlarmSummary

pub(all) struct AlarmSummary {
action : AlarmAction
trigger : String
description : String?
summary : String?
attendee_count : Int
} derive(Eq,
Debug
)

#
ByDayRule

pub(all) struct ByDayRule {
ordinal : Int?
weekday : Weekday
} derive(Eq,
Debug
)

#
Calendar

pub(all) struct Calendar {
properties : Array[Property]
components : Array[Component]
} derive(Eq,
Debug
)

#
Calendar::events

fn Calendar::events(self : Calendar) -> Array[Component]

#
Calendar::get

fn Calendar::get(self : Calendar, name : String) -> String?

#
Calendar::properties_named

fn Calendar::properties_named(self : Calendar, name : String) -> Array[Property]

#
CalendarChange

pub(all) struct CalendarChange {
kind : ChangeKind
uid : String
before : String?
after : String?
breaking : Bool
} derive(Eq,
Debug
)

#
CalendarDiff

pub(all) struct CalendarDiff {
compatible : Bool
changes : Array[CalendarChange]
} derive(Eq,
Debug
)

#
CalendarStats

pub(all) struct CalendarStats {
calendar_properties : Int
top_level_components : Int
total_components : Int
total_properties : Int
events : Int
todos : Int
journals : Int
timezones : Int
observances : Int
alarms : Int
recurring_components : Int
components_with_uid : Int
unknown_properties : Int
unsupported_properties : Int
} derive(Eq,
Debug
)

#
ChangeKind

pub(all) enum ChangeKind {
Added
Removed
Changed
} derive(Eq,
Debug
)

#
ChangeKind::name

fn ChangeKind::name(self : ChangeKind) -> String

#
Component

pub(all) struct Component {
name : String
properties : Array[Property]
components : Array[Component]
line : Int
} derive(Eq,
Debug
)

#
Component::alarms

fn Component::alarms(self : Component) -> Array[Component]

#
Component::children

fn Component::children(self : Component, name : String) -> Array[Component]

#
Component::count

fn Component::count(self : Component, name : String) -> Int

#
Component::get

fn Component::get(self : Component, name : String) -> String?

#
Component::has

fn Component::has(self : Component, name : String) -> Bool

#
Component::param_value

fn Component::param_value(self : Component, property : String, param : String) -> String?

#
Component::properties_named

fn Component::properties_named(self : Component, name : String) -> Array[Property]

#
ComponentRole

pub(all) enum ComponentRole {
CalendarRole
EventRole
TodoRole
JournalRole
TimezoneRole
ObservanceRole
AlarmRole
UnknownRole(String)
} derive(Eq,
Debug
)

#
ComponentRole::name

fn ComponentRole::name(self : ComponentRole) -> String

#
DurationValue

pub(all) struct DurationValue {
negative : Bool
weeks : Int
days : Int
hours : Int
minutes : Int
seconds : Int
} derive(Eq,
Debug
)

#
DurationValue::has_date_form

fn DurationValue::has_date_form(self : DurationValue) -> Bool

#
DurationValue::has_time_form

fn DurationValue::has_time_form(self : DurationValue) -> Bool

#
DurationValue::has_week_form

fn DurationValue::has_week_form(self : DurationValue) -> Bool

#
DurationValue::human_label

fn DurationValue::human_label(self : DurationValue) -> String

#
DurationValue::is_long_alarm_lead

fn DurationValue::is_long_alarm_lead(self : DurationValue) -> Bool

#
DurationValue::is_negative

fn DurationValue::is_negative(self : DurationValue) -> Bool

#
DurationValue::is_positive

fn DurationValue::is_positive(self : DurationValue) -> Bool

#
DurationValue::is_short_alarm_lead

fn DurationValue::is_short_alarm_lead(self : DurationValue) -> Bool

#
DurationValue::is_zero

fn DurationValue::is_zero(self : DurationValue) -> Bool

#
DurationValue::signed_seconds

fn DurationValue::signed_seconds(self : DurationValue) -> Int

#
DurationValue::total_seconds_abs

fn DurationValue::total_seconds_abs(self : DurationValue) -> Int

#
EventKey

pub(all) struct EventKey {
uid : String
summary : String
starts_at : String
ends_at : String
rrule : String
} derive(Eq,
Debug
)

#
EventSummary

pub(all) struct EventSummary {
uid : String
summary : String
starts_at : String
ends_at : String
status : String
location : String
recurring : Bool
alarm_count : Int
} derive(Eq,
Debug
)

#
Finding

pub(all) struct Finding {
severity : Severity
code : String
message : String
line : Int?
} derive(Eq,
Debug
)

#
Param

pub(all) struct Param {
name : String
values : Array[String]
} derive(Eq,
Debug
)

#
Property

pub(all) struct Property {
name : String
params : Array[Param]
value : String
line : Int
} derive(Eq,
Debug
)

#
Property::param_value

fn Property::param_value(self : Property, name : String) -> String?

#
PropertyCardinality

pub(all) enum PropertyCardinality {
RequiredOnce
OptionalOnce
OptionalMany
Many
} derive(Eq,
Debug
)

#
PropertyCardinality::name

fn PropertyCardinality::name(self : PropertyCardinality) -> String

#
PropertySpec

pub(all) struct PropertySpec {
name : String
kind : ValueKind
cardinality : PropertyCardinality
in_calendar : Bool
in_event : Bool
in_todo : Bool
in_journal : Bool
in_timezone : Bool
in_observance : Bool
in_alarm : Bool
note : String
} derive(Eq,
Debug
)

#
RecurrenceFrequency

pub(all) enum RecurrenceFrequency {
Secondly
Minutely
Hourly
Daily
Weekly
Monthly
Yearly
} derive(Eq,
Debug
)

#
RecurrenceFrequency::name

fn RecurrenceFrequency::name(self : RecurrenceFrequency) -> String

#
RecurrenceRule

pub(all) struct RecurrenceRule {
frequency : RecurrenceFrequency
interval : Int
count : Int?
until : String?
wkst : Weekday?
by_day : Array[ByDayRule]
by_month : Array[Int]
by_month_day : Array[Int]
by_set_pos : Array[Int]
} derive(Eq,
Debug
)

#
RecurrenceRule::density_hint

fn RecurrenceRule::density_hint(self : RecurrenceRule) -> String

#
RecurrenceRule::estimated_upper_bound

fn RecurrenceRule::estimated_upper_bound(self : RecurrenceRule) -> Int?

#
RecurrenceRule::frequency_score

fn RecurrenceRule::frequency_score(self : RecurrenceRule) -> Int

#
RecurrenceRule::has_by_rules

fn RecurrenceRule::has_by_rules(self : RecurrenceRule) -> Bool

#
RecurrenceRule::is_finite

fn RecurrenceRule::is_finite(self : RecurrenceRule) -> Bool

#
RecurrenceRule::limit_description

fn RecurrenceRule::limit_description(self : RecurrenceRule) -> String

#
RecurrenceRule::looks_dense_for_feed

fn RecurrenceRule::looks_dense_for_feed(self : RecurrenceRule) -> Bool

#
RecurrenceRule::shape_label

fn RecurrenceRule::shape_label(self : RecurrenceRule) -> String

#
RecurrenceRule::uses_month

fn RecurrenceRule::uses_month(self : RecurrenceRule, month : Int) -> Bool

#
RecurrenceRule::uses_month_day

fn RecurrenceRule::uses_month_day(self : RecurrenceRule, day : Int) -> Bool

#
RecurrenceRule::uses_weekday

fn RecurrenceRule::uses_weekday(self : RecurrenceRule, day : Weekday) -> Bool

#
Severity

pub(all) enum Severity {
Info
Warn
Deny
} derive(Eq,
Debug
)

#
Severity::name

fn Severity::name(self : Severity) -> String

#
ValidationOptions

pub(all) struct ValidationOptions {
require_prodid : Bool
require_version : Bool
max_events : Int?
allow_unknown_components : Bool
allow_floating_time : Bool
require_uid : Bool
require_dtstamp : Bool
} derive(Eq,
Debug
)

#
ValidationOptions::lenient

#
ValidationOptions::strict

#
ValidationReport

pub(all) struct ValidationReport {
accepted : Bool
findings : Array[Finding]
} derive(Eq,
Debug
)

#
ValueKind

pub(all) enum ValueKind {
Text
Date
DateTime
Duration
Uri
Integer
Boolean
Float
CalAddress
Period
Recurrence
UtcOffset
Unknown(String)
} derive(Eq,
Debug
)

#
ValueKind::name

fn ValueKind::name(self : ValueKind) -> String

#
Weekday

pub(all) enum Weekday {
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
} derive(Eq,
Debug
)

#
Weekday::abbr

fn Weekday::abbr(self : Weekday) -> String

#
alarm_action_name

fn alarm_action_name(alarm : Component) -> String

#
alarm_fingerprint

fn alarm_fingerprint(alarm : Component) -> String

#
alarm_has_absolute_trigger

fn alarm_has_absolute_trigger(alarm : Component) -> Bool

#
alarm_has_negative_lead

fn alarm_has_negative_lead(alarm : Component) -> Bool

#
alarm_has_positive_offset

fn alarm_has_positive_offset(alarm : Component) -> Bool

#
alarm_has_relative_trigger

fn alarm_has_relative_trigger(alarm : Component) -> Bool

#
alarm_is_action_supported

fn alarm_is_action_supported(action : AlarmAction) -> Bool

#
alarm_is_complete

fn alarm_is_complete(alarm : Component) -> Bool

#
alarm_is_long_notice

fn alarm_is_long_notice(alarm : Component) -> Bool

#
alarm_is_short_notice

fn alarm_is_short_notice(alarm : Component) -> Bool

#
alarm_lead_seconds_abs

fn alarm_lead_seconds_abs(alarm : Component) -> Int?

#
alarm_requires_attendee

fn alarm_requires_attendee(action : AlarmAction) -> Bool

#
alarm_requires_description

fn alarm_requires_description(action : AlarmAction) -> Bool

#
alarm_requires_summary

fn alarm_requires_summary(action : AlarmAction) -> Bool

#
alarm_trigger_kind

fn alarm_trigger_kind(alarm : Component) -> String

#
alarm_trigger_value

fn alarm_trigger_value(alarm : Component) -> String

#
all_day_events

fn all_day_events(calendar : Calendar) -> Array[Component]

#
all_property_specs

fn all_property_specs() -> Array[PropertySpec]

#
calendar_alarm_coverage_percent

fn calendar_alarm_coverage_percent(calendar : Calendar) -> Int

#
calendar_has_duplicate_event_uids

fn calendar_has_duplicate_event_uids(calendar : Calendar) -> Bool

#
calendar_has_uid

fn calendar_has_uid(calendar : Calendar, uid : String) -> Bool

#
calendar_recurrence_coverage_percent

fn calendar_recurrence_coverage_percent(calendar : Calendar) -> Int

#
calendar_status_count

fn calendar_status_count(calendar : Calendar, status : String) -> Int

#
cancelled_events

fn cancelled_events(calendar : Calendar) -> Array[Component]

#
cardinality_allows_many

fn cardinality_allows_many(cardinality : PropertyCardinality) -> Bool

#
cardinality_requires_once

fn cardinality_requires_once(cardinality : PropertyCardinality) -> Bool

#
catalog_support_summary

fn catalog_support_summary() -> String

#
collect_calendar_stats

fn collect_calendar_stats(calendar : Calendar) -> CalendarStats

#
compare_duration

fn compare_duration(a : DurationValue, b : DurationValue) -> Int

#
component_known_property_count

fn component_known_property_count(component : Component) -> Int

#
component_supported_property_count

fn component_supported_property_count(component : Component) -> Int

#
component_unknown_property_count

fn component_unknown_property_count(component : Component) -> Int

#
component_unsupported_property_count

fn component_unsupported_property_count(component : Component) -> Int

#
confirmed_events

fn confirmed_events(calendar : Calendar) -> Array[Component]

#
create_audio_alarm

fn create_audio_alarm(trigger : String) -> Component

#
create_display_alarm

fn create_display_alarm(trigger : String, description : String) -> Component

#
create_email_alarm

fn create_email_alarm(trigger : String, summary : String, description : String, attendee : String) -> Component

#
daily_rule

fn daily_rule(count : Int) -> RecurrenceRule

#
diff_calendars

fn diff_calendars(before : Calendar, after : Calendar) -> CalendarDiff

#
duplicate_event_uids

fn duplicate_event_uids(calendar : Calendar) -> Array[String]

#
duration_from_minutes

fn duration_from_minutes(minutes : Int) -> DurationValue

#
duration_from_seconds

fn duration_from_seconds(seconds : Int) -> DurationValue

#
event_alarm_count

fn event_alarm_count(event : Component) -> Int

#
event_alarm_fingerprint

fn event_alarm_fingerprint(event : Component) -> String

#
event_duration_text

fn event_duration_text(event : Component) -> String

#
event_end_value

fn event_end_value(event : Component) -> String

#
event_has_absolute_alarm

fn event_has_absolute_alarm(event : Component) -> Bool

#
event_has_alarms

fn event_has_alarms(event : Component) -> Bool

#
event_has_audio_alarm

fn event_has_audio_alarm(event : Component) -> Bool

#
event_has_category

fn event_has_category(event : Component, category : String) -> Bool

#
event_has_display_alarm

fn event_has_display_alarm(event : Component) -> Bool

#
event_has_email_alarm

fn event_has_email_alarm(event : Component) -> Bool

#
event_has_relative_alarm

fn event_has_relative_alarm(event : Component) -> Bool

#
event_is_all_day

fn event_is_all_day(event : Component) -> Bool

#
event_is_cancelled

fn event_is_cancelled(event : Component) -> Bool

#
event_is_confirmed

fn event_is_confirmed(event : Component) -> Bool

#
event_is_recurring

fn event_is_recurring(event : Component) -> Bool

#
event_is_tentative

fn event_is_tentative(event : Component) -> Bool

#
event_is_timed

fn event_is_timed(event : Component) -> Bool

#
event_key

fn event_key(event : Component) -> EventKey

#
event_location_text

fn event_location_text(event : Component) -> String

#
event_matches_text

fn event_matches_text(event : Component, needle : String) -> Bool

#
event_primary_rule

fn event_primary_rule(event : Component) -> RecurrenceRule?

#
event_recurrence_label

fn event_recurrence_label(event : Component) -> String

#
event_sort_key

fn event_sort_key(event : Component) -> String

#
event_start_date

fn event_start_date(event : Component) -> String?

#
event_start_value

fn event_start_value(event : Component) -> String

#
event_starts_on

fn event_starts_on(event : Component, date : String) -> Bool

#
event_status

fn event_status(event : Component) -> String

#
event_summaries

fn event_summaries(calendar : Calendar) -> Array[EventSummary]

#
event_summary_text

fn event_summary_text(event : Component) -> String

#
event_timezone

fn event_timezone(event : Component) -> String?

#
events_between_dates

fn events_between_dates(calendar : Calendar, start_date : String, end_date : String) -> Array[Component]

#
events_on_date

fn events_on_date(calendar : Calendar, date : String) -> Array[Component]

#
events_with_alarms

fn events_with_alarms(calendar : Calendar) -> Array[Component]

#
events_with_category

fn events_with_category(calendar : Calendar, category : String) -> Array[Component]

#
events_with_status

fn events_with_status(calendar : Calendar, status : String) -> Array[Component]

#
find_event_by_uid

fn find_event_by_uid(calendar : Calendar, uid : String) -> Component?

#
find_property_spec

fn find_property_spec(name : String) -> PropertySpec?

#
fixture_alarm_calendar

fn fixture_alarm_calendar() -> String

#
fixture_bad_rrule_calendar

fn fixture_bad_rrule_calendar() -> String

#
fixture_changed_calendar

fn fixture_changed_calendar() -> String

#
fixture_folded_calendar

fn fixture_folded_calendar() -> String

#
fixture_invalid_calendar

fn fixture_invalid_calendar() -> String

#
fixture_recurring_calendar

fn fixture_recurring_calendar() -> String

#
fixture_timezone_calendar

fn fixture_timezone_calendar() -> String

#
fixture_valid_calendar

fn fixture_valid_calendar() -> String

#
fold_line

fn fold_line(line : String) -> String

#
is_duration_text

fn is_duration_text(input : String) -> Bool

#
is_known_property

fn is_known_property(name : String) -> Bool

#
known_properties_for_role

fn known_properties_for_role(role : ComponentRole) -> Array[String]

#
known_property_names

fn known_property_names() -> Array[String]

#
monthly_nth_weekday_rule

fn monthly_nth_weekday_rule(count : Int, ordinal : Int, weekday : Weekday) -> RecurrenceRule

#
normalize_duration

fn normalize_duration(input : String) -> Result[String, DurationError]

#
normalize_recurrence_rule

fn normalize_recurrence_rule(input : String) -> Result[String, RecurrenceError]

#
parse_alarm_action

fn parse_alarm_action(value : String) -> AlarmAction

#
parse_calendar

fn parse_calendar(input : String) -> Result[Calendar, CalError]

#
parse_content_line

fn parse_content_line(raw : String, line : Int) -> Property raise CalError

#
parse_duration

fn parse_duration(input : String) -> Result[DurationValue, DurationError]

#
parse_recurrence_rule

fn parse_recurrence_rule(input : String) -> Result[RecurrenceRule, RecurrenceError]

#
property_allowed_in_component

fn property_allowed_in_component(name : String, component_name : String) -> Bool

#
property_allowed_in_role

fn property_allowed_in_role(name : String, role : ComponentRole) -> Bool

#
property_cardinality

fn property_cardinality(name : String) -> PropertyCardinality

#
property_value_kind

fn property_value_kind(name : String) -> ValueKind

#
recurrence_rule_from_parts

fn recurrence_rule_from_parts(frequency : RecurrenceFrequency, interval : Int, count : Int?, until : String?) -> RecurrenceRule

#
recurring_events

fn recurring_events(calendar : Calendar) -> Array[Component]

#
render_agenda

fn render_agenda(calendar : Calendar) -> String

#
render_agenda_event

fn render_agenda_event(event : Component) -> String

#
render_agenda_for_date

fn render_agenda_for_date(calendar : Calendar, date : String) -> String

#
render_alarm_summary

fn render_alarm_summary(alarm : Component) -> String

#
render_calendar

fn render_calendar(calendar : Calendar) -> String

#
render_calendar_json

fn render_calendar_json(calendar : Calendar) -> String

#
render_calendar_report

fn render_calendar_report(calendar : Calendar) -> String

#
render_diff

fn render_diff(diff : CalendarDiff) -> String

#
render_duration

fn render_duration(value : DurationValue) -> String

#
render_event_alarms

fn render_event_alarms(event : Component) -> String

#
render_event_summary

fn render_event_summary(summary : EventSummary) -> String

#
render_event_summary_json

fn render_event_summary_json(summary : EventSummary) -> String

#
render_finding_json

fn render_finding_json(finding : Finding) -> String

#
render_property

fn render_property(prop : Property) -> String

#
render_property_catalog

fn render_property_catalog() -> String

#
render_property_spec

fn render_property_spec(spec : PropertySpec) -> String

#
render_recurrence_rule

fn render_recurrence_rule(rule : RecurrenceRule) -> String

#
render_role_catalog

fn render_role_catalog(role : ComponentRole) -> String

#
render_stats_json

fn render_stats_json(stats : CalendarStats) -> String

#
render_stats_line

fn render_stats_line(stats : CalendarStats) -> String

#
render_validation

fn render_validation(report : ValidationReport) -> String

#
role_for_component

fn role_for_component(name : String) -> ComponentRole

#
search_events

fn search_events(calendar : Calendar, needle : String) -> Array[Component]

#
spec_allows_role

fn spec_allows_role(spec : PropertySpec, role : ComponentRole) -> Bool

#
stats_complexity_label

fn stats_complexity_label(stats : CalendarStats) -> String

#
stats_feature_label

fn stats_feature_label(stats : CalendarStats) -> String

#
stats_health_score

fn stats_health_score(stats : CalendarStats) -> Int

#
summarize_alarm

fn summarize_alarm(alarm : Component) -> AlarmSummary

#
summarize_event

fn summarize_event(event : Component) -> EventSummary

#
tentative_events

fn tentative_events(calendar : Calendar) -> Array[Component]

#
timed_events

fn timed_events(calendar : Calendar) -> Array[Component]

#
trigger_is_absolute

fn trigger_is_absolute(input : String) -> Bool

#
trigger_is_relative

fn trigger_is_relative(input : String) -> Bool

#
trigger_kind

fn trigger_kind(input : String) -> String

#
validate_calendar

fn validate_calendar(calendar : Calendar, options : ValidationOptions) -> ValidationReport

#
weekly_rule

fn weekly_rule(count : Int, days : Array[Weekday]) -> RecurrenceRule