diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa8c9dbc..b1f6071a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Added option to calendar module that colors only the symbol instead of the whole line
- Added option for new display format in the calendar module with date headers with times/events below.
- Ability to fetch compliments from a remote server
+- Add regex filtering to calendar module
### Changed
- Upgrade to Electron 2.0.0.
diff --git a/modules/default/calendar/README.md b/modules/default/calendar/README.md
index 7a60cfaf..e63f95b2 100755
--- a/modules/default/calendar/README.md
+++ b/modules/default/calendar/README.md
@@ -48,7 +48,7 @@ The following properties can be configured:
| `broadcastEvents` | If this property is set to true, the calendar will broadcast all the events to all other modules with the notification message: `CALENDAR_EVENTS`. The event objects are stored in an array and contain the following fields: `title`, `startDate`, `endDate`, `fullDayEvent`, `location` and `geo`.
**Possible values:** `true`, `false`
**Default value:** `true`
| `hidePrivate` | Hides private calendar events.
**Possible values:** `true` or `false`
**Default value:** `false`
| `hideOngoing` | Hides calendar events that have already started.
**Possible values:** `true` or `false`
**Default value:** `false`
-| `excludedEvents` | An array of words / phrases from event titles that will be excluded from being shown.
Additionally advanced filter objects can be passed in. Below is the configuration for the advance filtering object.
**Required**
`filterBy` - string used to determine if filter is applied.
**Optional**
`until` - Time before an event to display it Ex: [`'3 days'`, `'2 months'`, `'1 week'`]
`caseSensitive` - By default, excludedEvents are case insensitive, set this to true to enforce case sensitivity
**Example:** `['Birthday', 'Hide This Event', {filterBy: 'Payment', until: '6 days', caseSensitive: true}]`
**Default value:** `[]`
+| `excludedEvents` | An array of words / phrases from event titles that will be excluded from being shown.
Additionally advanced filter objects can be passed in. Below is the configuration for the advance filtering object.
**Required**
`filterBy` - string used to determine if filter is applied.
**Optional**
`until` - Time before an event to display it Ex: [`'3 days'`, `'2 months'`, `'1 week'`]
`caseSensitive` - By default, excludedEvents are case insensitive, set this to true to enforce case sensitivity
`regex` - set to `true` if filterBy is a regex. For those not familiar with regex it is used for pattern matching, please see [here](https://regexr.com/) for more info.
**Example:** `['Birthday', 'Hide This Event', {filterBy: 'Payment', until: '6 days', caseSensitive: true}, {filterBy: '^[0-9]{1,}.*', regex: true}]`
**Default value:** `[]`
### Calendar configuration
diff --git a/modules/default/calendar/calendarfetcher.js b/modules/default/calendar/calendarfetcher.js
index 911eaba4..ccd1f6c8 100644
--- a/modules/default/calendar/calendarfetcher.js
+++ b/modules/default/calendar/calendarfetcher.js
@@ -119,19 +119,29 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
for (var f in excludedEvents) {
var filter = excludedEvents[f],
testTitle = title.toLowerCase(),
- until = null;
+ until = null,
+ useRegex = false,
+ regexFlags = "g";
if (filter instanceof Object) {
if (typeof filter.until !== "undefined") {
until = filter.until;
}
+ if (typeof filter.regex !== "undefined") {
+ useRegex = filter.regex;
+ }
+
// If additional advanced filtering is added in, this section
// must remain last as we overwrite the filter object with the
// filterBy string
if (filter.caseSensitive) {
filter = filter.filterBy;
testTitle = title;
+ } else if (useRegex) {
+ filter = filter.filterBy;
+ testTitle = title;
+ regexFlags += "i";
} else {
filter = filter.filterBy.toLowerCase();
}
@@ -139,7 +149,7 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
filter = filter.toLowerCase();
}
- if (testTitle.includes(filter)) {
+ if (testTitleByFilter(testTitle, filter, useRegex, regexFlags)) {
if (until) {
dateFilter = until;
} else {
@@ -294,6 +304,22 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
return false;
};
+ var testTitleByFilter = function (title, filter, useRegex, regexFlags) {
+ if (useRegex) {
+ // Assume if leading slash, there is also trailing slash
+ if (filter[0] === "/") {
+ // Strip leading and trailing slashes
+ filter = filter.substr(1).slice(0, -1);
+ }
+
+ filter = new RegExp(filter, regexFlags);
+
+ return filter.test(title);
+ } else {
+ return title.includes(filter);
+ }
+ }
+
/* public methods */
/* startFetch()