Repository: adamgibbons/ics
Pull request #203 (2021-11-11 15:29:18)

added classfication as iCalendar CLASS Value
I added the CLASS Value to the options.
Also added it to the tests and bumped the Version.

I named it classification as class is a reserved Name.
The specification says that all text values are allowed so I added the standard Values and all strings.

#201


Patch:
diff --git a/README.md b/README.md
index 58f74d9..4f1370d 100644
--- a/README.md
+++ b/README.md
@@ -233,6 +233,7 @@ The following properties are accepted:
 | recurrenceRule        | A recurrence rule, commonly referred to as an RRULE, defines the repeat pattern or rule for to-dos, journal entries and events. If specified, RRULE can be used to compute the recurrence set (the complete set of recurrence instances in a calendar component). You can use a generator like this [one](https://www.textmagic.com/free-tools/rrule-generator) | `FREQ=DAILY`
 | sequence      | For sending an update for an event (with the same uid), defines the revision sequence number. | `2`
 | busyStatus    | Used to specify busy status for Microsoft applications, like Outlook. See [Microsoft spec](https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcical/cd68eae7-ed65-4dd3-8ea7-ad585c76c736). | `'BUSY'` OR `'FREE'` OR `'TENTATIVE`' OR `'OOF'`
+| classification    | This property defines the access classification for a calendar component. See [iCalender spec](https://icalendar.org/iCalendar-RFC-5545/3-8-1-3-classification.html). | `'PUBLIC'` OR `'PRIVATE'` OR `'CONFIDENTIAL`' OR any non-standard string
 | created | Date-time representing event's creation date. Provide a date-time in UTC | [2000, 1, 5, 10, 0] (January 5, 2000 GMT +00:00)
 | lastModified | Date-time representing date when event was last modified. Provide a date-time in UTC | [2000, 1, 5, 10, 0] (January 5, 2000 GMT +00:00)
 | calName       |  Specifies the _calendar_ (not event) name. Used by Apple iCal and Microsoft Outlook; see [Open Specification](https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcical/1da58449-b97e-46bd-b018-a1ce576f3e6d) | `'Example Calendar'` |
diff --git a/index.d.ts b/index.d.ts
index f899751..1ce0bf8 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -48,6 +48,11 @@ export type Attendee = Person & {
 
 export type ActionType = 'audio' | 'display' | 'email' | 'procedure';
 
+/**
+ * This property defines the access classification for a calendar component.
+ */
+export type classificationType = 'PUBLIC' | 'PRIVATE' | 'CONFIDENTIAL' | string;
+
 export type Alarm = {
   action?: ActionType;
   trigger?: DurationObject; // @todo DateArray | DurationObject;
@@ -73,19 +78,20 @@ export type EventAttributes = {
   url?: string;
   status?: EventStatus;
   busyStatus?: 'FREE' | 'BUSY' | 'TENTATIVE' | 'OOF';
-
+  
   organizer?: Person;
   attendees?: Attendee[];
-
+  
   categories?: string[];
   alarms?: Alarm[];
-
+  
   productId?: string;
   uid?: string;
   method?: string;
   recurrenceRule?: string;
   sequence?: number;
   calName?: string;
+  classification?: classificationType;
   created?: DateArray;
   lastModified?: DateArray;
 } & ({ end: DateArray } | { duration: DurationObject });
diff --git a/notes.md b/notes.md
index 70c226f..297c5fe 100644
--- a/notes.md
+++ b/notes.md
@@ -46,7 +46,7 @@ TZID=America/New_York:19980119T020000
 - [x] dtstart
 
 ### OPTIONAL but MUST NOT occur more than once
-- [ ] class
+- [x] class
 - [ ] created
 - [x] description
 - [x] geo
diff --git a/package.json b/package.json
index 3a411f8..5453e6b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "ics",
-  "version": "2.31.0",
+  "version": "2.32.0",
   "description": "iCal (ics) file generator",
   "main": "index.js",
   "types": "index.d.ts",
diff --git a/src/pipeline/format.js b/src/pipeline/format.js
index 247127c..a0fa8ef 100644
--- a/src/pipeline/format.js
+++ b/src/pipeline/format.js
@@ -38,6 +38,7 @@ export default function formatEvent(attributes = {}) {
     alarms,
     recurrenceRule,
     busyStatus,
+    classification,
     created,
     lastModified,
     calName
@@ -75,6 +76,7 @@ export default function formatEvent(attributes = {}) {
   icsFormat += categories ? (foldLine(`CATEGORIES:${categories}`) + '\r\n') : ''
   icsFormat += organizer ? (foldLine(`ORGANIZER;${setOrganizer(organizer)}`) + '\r\n') : ''
   icsFormat += busyStatus ? (foldLine(`X-MICROSOFT-CDO-BUSYSTATUS:${busyStatus}`) + '\r\n') : ''
+  icsFormat += classification ? (foldLine(`CLASS:${classification}`) + '\r\n') : ''
   icsFormat += created ? ('CREATED:' + formatDate(created) + '\r\n') : ''
   icsFormat += lastModified ? ('LAST-MODIFIED:' + formatDate(lastModified) + '\r\n') : ''
   if (attendees) {
diff --git a/src/schema/index.js b/src/schema/index.js
index 3a99951..a75c308 100644
--- a/src/schema/index.js
+++ b/src/schema/index.js
@@ -83,6 +83,7 @@ const schema = yup.object().shape({
   alarms: yup.array().of(alarmSchema),
   recurrenceRule: yup.string(),
   busyStatus: yup.string().matches(/TENTATIVE|FREE|BUSY|OOF/i),
+  classification: yup.string(),
   created: dateTimeSchema,
   lastModified: dateTimeSchema,
   calName: yup.string()


Test patch:
diff --git a/test/pipeline/format.spec.js b/test/pipeline/format.spec.js
index dd1e830..5e814ba 100644
--- a/test/pipeline/format.spec.js
+++ b/test/pipeline/format.spec.js
@@ -186,6 +186,20 @@ describe('pipeline.formatEvent', () => {
     expect(formattedEventTent).to.contain('X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE')
     expect(formattedEventOOF).to.contain('X-MICROSOFT-CDO-BUSYSTATUS:OOF')
   })
+  it('writes a access classification', () => {
+    const eventPublic = buildEvent({ classification: "PUBLIC" })
+    const eventPrivate = buildEvent({ classification: "PRIVATE"})
+    const eventConfidential = buildEvent({ classification: "CONFIDENTIAL"})
+    const eventAnyClass = buildEvent({ classification: "non-standard-property" })
+    const formattedEventPublic = formatEvent(eventPublic)
+    const formattedEventPrivate = formatEvent(eventPrivate)
+    const formattedEventConfidential = formatEvent(eventConfidential)
+    const formattedEventAnyClass = formatEvent(eventAnyClass)
+    expect(formattedEventPublic).to.contain('CLASS:PUBLIC')
+    expect(formattedEventPrivate).to.contain('CLASS:PRIVATE')
+    expect(formattedEventConfidential).to.contain('CLASS:CONFIDENTIAL')
+    expect(formattedEventAnyClass).to.contain('CLASS:non-standard-property')
+  })
   it('writes an organizer', () => {
     const event = formatEvent({ organizer: {
       name: 'Adam Gibbons',