├── CHANGELOG.md
├── renovate.json
├── babel.config.js
├── public
├── favicon.ico
└── index.html
├── src
├── main.js
├── plugin.js
├── App.vue
└── index.js
├── docs
├── README.md
├── .vuepress
│ ├── plugin.js
│ └── config.js
├── started.md
└── installation.md
├── .gitignore
├── LICENSE
├── package.json
├── README.md
└── dist
├── vue-ics.umd.min.js
├── vue-ics.esm.js
├── vue-ics.common.js
└── vue-ics.umd.js
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | // TODO: release log here ...
2 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evildvl/vue-ics/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import './plugin'
4 |
5 | Vue.config.productionTip = false
6 |
7 | new Vue({
8 | render: h => h(App),
9 | }).$mount('#app')
10 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | `VueIcs` plugin is plugin for [Vue.js](http://vuejs.org).
4 | Features include:
5 |
6 | - Feature1
7 | - Feature2
8 | - ...
9 |
10 | [Get started](./started/) or play with the [demo](https://github.com//vue-ics/tree/dev/demo) (see [`README.md`](https://github.com//vue-ics/) to run them).
11 |
--------------------------------------------------------------------------------
/src/plugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * NOTE:
3 | * This file is plugin stub for main.js
4 | */
5 |
6 | import Vue from 'vue'
7 | import plugin from './index'
8 |
9 | Vue.use(plugin)
10 |
11 | /*
12 | * NOTE:
13 | * If you want Vue instance of main.js to import something in your plugin as a Vue option,
14 | * you need to export it here.
15 | */
16 | // export default plugin
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | public
4 | dist/*.gz
5 | dist/*.map
6 | coverage
7 | docs/.vuepress/dist
8 |
9 | # local env files
10 | .env.local
11 | .env.*.local
12 |
13 | # related test files
14 | /tests/e2e/reports
15 | /tests/e2e/videos
16 | /tests/e2e/screenshots
17 |
18 | # editor directories and files
19 | .idea
20 | .vscode
21 | *.suo
22 | *.ntvs*
23 | *.njsproj
24 | *.sln
25 | *.sw*
26 |
--------------------------------------------------------------------------------
/docs/.vuepress/plugin.js:
--------------------------------------------------------------------------------
1 | const { version } = require('../../package.json')
2 |
3 | module.exports = (/*options, ctx*/) => ({
4 | async enhanceAppFiles () {
5 | const code = `export default ({ Vue }) => {
6 | Vue.mixin({
7 | computed: {
8 | $version () {
9 | return '${version}'
10 | }
11 | }
12 | })
13 | }`
14 | return [{
15 | name: 'vuepress-plugin-vue-cli-plugin-p11n',
16 | content: code
17 | }]
18 | }
19 | })
20 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | vue-ics
9 |
10 |
11 |
12 | We're sorry but vue-ics doesn't work properly without JavaScript enabled. Please enable it to continue.
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('./plugin.js')
4 | ],
5 | locales: {
6 | '/': {
7 | lang: 'en-US',
8 | title: 'VueIcs',
9 | description: 'VueIcs for Vue.js'
10 | }
11 | },
12 | themeConfig: {
13 | repo: '/vue-ics',
14 | docsDir: 'docs',
15 | locales: {
16 | '/': {
17 | label: 'English',
18 | selectText: 'Languages',
19 | editLinkText: 'Edit this page on GitHub',
20 | nav: [{
21 | text: 'Release Notes',
22 | link: 'https://github.com//vue-ics/releases'
23 | }],
24 | sidebar: [
25 | '/installation.md',
26 | '/started.md',
27 | ]
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/docs/started.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | > We will be using [ES2015](https://github.com/lukehoban/es6features) in the code samples in the guide.
4 |
5 |
6 | ## HTML
7 |
8 | ```html
9 |
10 |
11 |
12 |
13 |
14 |
15 | ```
16 |
17 | ## JavaScript
18 |
19 | ```javascript
20 | // If using a module system (e.g. via Vue CLI), import Vue and vue-ics and then call Vue.use(vue-ics).
21 | // import Vue from 'vue'
22 | // import vue-ics from 'vue-ics'
23 | //
24 | // Vue.use(vue-ics)
25 |
26 | // NOTE: here the example
27 |
28 | // Now the app has started!
29 | new Vue({ }).$mount('#app')
30 | ```
31 |
32 | Output the following:
33 |
34 | ```html
35 |
36 |
37 |
38 | ```
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2019
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/docs/installation.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | ## Direct Download / CDN
4 |
5 | https://unpkg.com/vue-ics/dist/vue-ics
6 |
7 | [unpkg.com](https://unpkg.com) provides NPM-based CDN links. The above link will always point to the latest release on NPM. You can also use a specific version/tag via URLs like https://unpkg.com/vue-ics@{{ $version }}/dist/vue-ics.js
8 |
9 | Include vue-ics after Vue and it will install itself automatically:
10 |
11 | ```html
12 |
13 |
14 | ```
15 |
16 | ## NPM
17 |
18 | ```sh
19 | $ npm install vue-ics
20 | ```
21 |
22 | ## Yarn
23 |
24 | ```sh
25 | $ yarn add vue-ics
26 | ```
27 |
28 | When used with a module system, you must explicitly install the `vue-ics` via `Vue.use()`:
29 |
30 | ```javascript
31 | import Vue from 'vue'
32 | import vue-ics from 'vue-ics'
33 |
34 | Vue.use(vue-ics)
35 | ```
36 |
37 | You don't need to do this when using global script tags.
38 |
39 | ## Dev Build
40 |
41 | You will have to clone directly from GitHub and build `vue-ics` yourself if
42 | you want to use the latest dev build.
43 |
44 | ```sh
45 | $ git clone https://github.com//vue-ics.git node_modules/vue-ics
46 | $ cd node_modules/vue-ics
47 | $ npm install
48 | $ npm run build
49 | ```
50 |
51 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
44 |
67 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-ics",
3 | "description": "Vue.js plugin for generating ICalendar (.ics) files.",
4 | "version": "0.1.4",
5 | "author": "Stanislav Mihaylov ",
6 | "license": "MIT",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/evildvl/vue-ics.git"
10 | },
11 | "scripts": {
12 | "serve": "vue-cli-service serve",
13 | "build": "vue-cli-service build",
14 | "lint": "vue-cli-service lint",
15 | "demo": "vue-cli-service demo",
16 | "docs": "npm run docs:serve",
17 | "docs:build": "vue-cli-service docs --mode build",
18 | "docs:serve": "vue-cli-service docs --mode serve",
19 | "prepublish": "vue-cli-service lint && vue-cli-service build",
20 | "start": "vue-cli-service serve"
21 | },
22 | "main": "dist/vue-ics.common.js",
23 | "module": "dist/vue-ics.esm.js",
24 | "unpkg": "dist/vue-ics.umd.min.js",
25 | "files": [
26 | "dist/vue-ics.common.js",
27 | "dist/vue-ics.umd.min.js",
28 | "dist/vue-ics.umd.js",
29 | "dist/vue-ics.esm.js",
30 | "src"
31 | ],
32 | "dependencies": {
33 | "core-js": "^3.0.0",
34 | "file-saver": "^2.0.2"
35 | },
36 | "devDependencies": {
37 | "@vue/cli-plugin-babel": "4.5.3",
38 | "@vue/cli-plugin-eslint": "4.5.3",
39 | "@vue/cli-service": "4.5.3",
40 | "babel-eslint": "10.1.0",
41 | "cz-conventional-changelog": "3.2.0",
42 | "eslint": "7.7.0",
43 | "eslint-plugin-vue": "6.2.2",
44 | "vue": "2.6.11",
45 | "vue-cli-plugin-p11n": "0.4.0",
46 | "vue-template-compiler": "2.6.11"
47 | },
48 | "eslintConfig": {
49 | "root": true,
50 | "env": {
51 | "node": true
52 | },
53 | "extends": [
54 | "plugin:vue/essential",
55 | "eslint:recommended"
56 | ],
57 | "rules": {},
58 | "parserOptions": {
59 | "parser": "babel-eslint"
60 | }
61 | },
62 | "postcss": {
63 | "plugins": {
64 | "autoprefixer": {}
65 | }
66 | },
67 | "browserslist": [
68 | "> 1%",
69 | "last 2 versions"
70 | ],
71 | "jsdelivr": "dist/vue-ics.umd.min.js",
72 | "sideeffects": false,
73 | "config": {
74 | "commitizen": {
75 | "path": "./node_modules/cz-conventional-changelog"
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/sindresorhus/awesome)
2 | [](https://badge.fury.io/js/vue-ics)
3 | [](https://lgtm.com/projects/g/evildvl/vue-ics/alerts/)
4 | [](https://lgtm.com/projects/g/evildvl/vue-ics/context:javascript)
5 | [](https://conventionalcommits.org)
6 |
7 | # vue-ics
8 |
9 | Vue.js plugin for generating ICalendar (.ics) files.
10 |
11 | ## Installation
12 |
13 | ##### NPM
14 |
15 | ```
16 | npm install vue-ics --save
17 | ```
18 |
19 | ##### Vue
20 |
21 | ```javascript
22 | import Vue from 'vue'
23 | import ICS from 'vue-ics'
24 |
25 | Vue.use(ICS, options)
26 | ```
27 |
28 | ## Initialising options (optional)
29 | {string} uidDomain - Your domain
30 |
31 | {string} prodId - Product ID
32 |
33 | ## Create event
34 |
35 | {string} language - Language in format en-us (default)
36 |
37 | {string} subject - Subject/Title of event
38 |
39 | {string} description - Description of event
40 |
41 | {string} location - Location of event
42 |
43 | {string} begin - Beginning date of event
44 |
45 | {string} stop - Ending date of event
46 |
47 | {string} url - URL (optional)
48 |
49 | {object} organizer - Organizer
50 |
51 | {string} name - Organizer name
52 |
53 | {string} email - Organizer email
54 |
55 | {RRule} rrule - Reccurence rule (optional)
56 |
57 | ```javascript
58 | this.$ics.addEvent(language, subject, description, location, begin, stop, url, organizer, rrule)
59 | ```
60 | You can add one or more events.
61 |
62 | ## Reccurence rule
63 | You can add recurrence rule for your event. Event will be repeat as you want.
64 | ```javascript
65 | const rrule = {
66 | freq: 'WEEKLY',
67 | until: until,
68 | interval: 1
69 | }
70 | ```
71 |
72 | Parameters:
73 |
74 | {string} freq - Required. The frequency of event recurrence. Can be DAILY, WEEKLY, MONTHLY, or YEARLY.
75 |
76 | {string | number | Date} until - date stringA date string representing the date on which to end repitition. Must be friendly to Date()
77 |
78 | {number} interval - The interval of freq to recur at. For example, if freq is WEEKLY and interval is 2, the event will repeat every 2 weeks
79 |
80 | {array} byday - Which days of the week the event is to occur. An array containing any of SU, MO, TU, WE, TH, FR, SA
81 |
82 | ## Remove all events from the calendar
83 |
84 | ```javascript
85 | this.$ics.removeAllEvents()
86 | ```
87 |
88 | ## Get calendar with events as string
89 |
90 | ```javascript
91 | this.$ics.calendar()
92 | ```
93 |
94 | ##Download calendar file
95 |
96 | ```javascript
97 | this.$ics.download(fileName)
98 | ```
99 |
100 | {string} fileName - name of file without extension (will be *.ics)
101 |
--------------------------------------------------------------------------------
/dist/vue-ics.umd.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-ics v0.1.3
3 | * (c) 2020 Stanislav Mihaylov
4 | * Released under the MIT License.
5 | */
6 | !function(n,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("file-saver")):"function"==typeof define&&define.amd?define(["file-saver"],t):(n=n||self,n.VueIcs=t(n.fileSaver))}(this,function(n){"use strict";function t(n){var t=0,e=["SU","MO","TU","WE","TH","FR","SA"];if("YEARLY"!==n.freq&&"MONTHLY"!==n.freq&&"WEEKLY"!==n.freq&&"DAILY"!==n.freq)throw t+=1,"Recurrence rrule frequency must be provided and be one of the following: 'YEARLY', 'MONTHLY', 'WEEKLY', or 'DAILY'";if(n.until&&isNaN(Date.parse(n.until)))throw t+=1,"Recurrence rrule 'until' must be a valid date string";if(n.interval&&isNaN(parseInt(n.interval)))throw t+=1,"Recurrence rrule 'interval' must be an integer";if(n.count&&isNaN(parseInt(n.count)))throw t+=1,"Recurrence rrule 'count' must be an integer";if(void 0!==n.byday){if("[object Array]"!==Object.prototype.toString.call(n.byday))throw t+=1,"Recurrence rrule 'byday' must be an array";if(n.byday.length>7)throw t+=1,"Recurrence rrule 'byday' array must not be longer than the 7 days in a week";n.byday=n.byday.filter(function(t,e){return n.byday.indexOf(t)==e});for(var c in n.byday)if(e.indexOf(n.byday[c])<0)throw t+=1,"Recurrence rrule 'byday' values must include only the following: 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'"}return 0===t}function e(n){return"\n".concat(n,"\n")}function c(){return a++}var o=[],a=0,r=function(a){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{uidDomain:"evildvl",prodId:"vueICS"};a.prototype.$ics={removeAllEvents:function(){o=[]},addEvent:function(){var n,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"en-us",a=arguments.length>1?arguments[1]:void 0,i=arguments.length>2?arguments[2]:void 0,l=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"none",u=arguments.length>4?arguments[4]:void 0,s=arguments.length>5?arguments[5]:void 0,d=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null,g=arguments.length>7&&void 0!==arguments[7]?arguments[7]:null,f=arguments.length>8&&void 0!==arguments[8]?arguments[8]:null;if(void 0===a||void 0===i||void 0===l||void 0===u||void 0===s)throw"You need to specify function arguments";if(f&&t(f)){if(n="RRULE:FREQ=".concat(f.freq),f.until){var v=new Date(Date.parse(f.until)).toISOString();n+=";UNTIL=".concat(v.substring(0,v.length-13).replace(/[-]/g,""),"000000Z")}f.interval&&(n+=";INTERVAL=".concat(f.interval)),f.count&&(n+=";COUNT=".concat(f.count)),f.byday&&f.byday.length>0&&(n+=";BYDAY=".concat(f.byday.join(",")))}var y=new Date(u),E=new Date(s),S=new Date,D="".concat(S.getDay()).concat(S.getMonth()).concat(S.getFullYear(),"-").concat(S.getHours()).concat(S.getMinutes()).concat(S.getSeconds()).concat(c()),A="0000".concat(y.getFullYear().toString()).slice(-4),h="00".concat((y.getMonth()+1).toString()).slice(-2),N="00".concat(y.getDate().toString()).slice(-2),R="00".concat(y.getHours().toString()).slice(-2),T="00".concat(y.getMinutes().toString()).slice(-2),I="00".concat(y.getSeconds().toString()).slice(-2),b="0000".concat(E.getFullYear().toString()).slice(-4),p="00".concat((E.getMonth()+1).toString()).slice(-2),w="00".concat(E.getDate().toString()).slice(-2),L="00".concat(E.getHours().toString()).slice(-2),m="00".concat(E.getMinutes().toString()).slice(-2),M="00".concat(E.getSeconds().toString()).slice(-2),O="0000".concat(S.getFullYear().toString()).slice(-4),Y="00".concat((S.getMonth()+1).toString()).slice(-2),V="00".concat(S.getDate().toString()).slice(-2),U="00".concat(S.getHours().toString()).slice(-2),C="00".concat(S.getMinutes().toString()).slice(-2),H="00".concat(S.getSeconds().toString()).slice(-2),q="",F="";R+T+I+L+m+M!=0&&(q="T".concat(R).concat(T).concat(I),F="T".concat(L).concat(m).concat(M));var j="T".concat(U).concat(C).concat(H),x=A+h+N+q,G=b+p+w+F,B=O+Y+V+j,P="\n BEGIN:VEVENT\n UID:".concat(D,"@").concat(r.uidDomain,"\n ").concat(d?"URL:"+d:"","\n DESCRIPTION:").concat(i).concat(n?"\n"+n:"","\n DTSTAMP;VALUE=DATE-TIME:").concat(B,",\n DTSTART;VALUE=DATE-TIME:").concat(x,"\n DTEND;VALUE=DATE-TIME:").concat(G,"\n LOCATION:").concat(l,"\n ").concat(g?"ORGANIZER;CN="+g.name+":MAILTO:"+g.email:"","\n SUMMARY;LANGUAGE=").concat(e,":").concat(a,"\n END:VEVENT\n ");return o.push(P),P},calendar:function(){return e("\n BEGIN:VCALENDAR\n PRODID:".concat(r.prodId,"\n VERSION:2.0\n ").concat(o.join("\n"),"\n END:VCALENDAR\n\n ").replace(/^\s*[\r\n]/gm,"").replace(/^\s+/gm,""))},download:function(t){var c=e("\n BEGIN:VCALENDAR\n PRODID:".concat(r.prodId,"\n VERSION:2.0\n ").concat(o.join("\n"),"\n END:VCALENDAR\n\n ").replace(/^\s*[\r\n]/gm,"").replace(/^\s+/gm,"")),a=new Blob([c],{type:"text/x-vCalendar;charset=utf-8"});n.saveAs(a,"".concat(t,".ics"))}}},i={install:r,version:"0.1.3"};return"undefined"!=typeof window&&window.Vue&&window.Vue.use(i),i});
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { saveAs } from 'file-saver'
2 | const version = '__VERSION__'
3 |
4 | /**
5 | * Reccurence rule
6 | * @typedef {Object} RRule
7 | * @property {string} freq - Required. The frequency of event recurrence. Can be DAILY, WEEKLY, MONTHLY, or YEARLY.
8 | * @property {string | number | Date} until - date stringA date string representing the date on which to end repitition. Must be friendly to Date()
9 | * @property {number} interval - The interval of freq to recur at. For example, if freq is WEEKLY and interval is 2, the event will repeat every 2 weeks
10 | * @property {array} byday - Which days of the week the event is to occur. An array containing any of SU, MO, TU, WE, TH, FR, SA
11 | */
12 |
13 | var Events = []
14 |
15 | /**
16 | * Reccurence rule validation
17 | * @function
18 | * @param {RRule} rrule - Reccurence rule
19 | * @returns {boolean}
20 | */
21 | function validateRepeatRule(rrule) {
22 | let counter = 0
23 | const BYDAY_VALUES = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']
24 | if (rrule.freq !== 'YEARLY' && rrule.freq !== 'MONTHLY' && rrule.freq !== 'WEEKLY' && rrule.freq !== 'DAILY') {
25 | counter += 1
26 | throw "Recurrence rrule frequency must be provided and be one of the following: 'YEARLY', 'MONTHLY', 'WEEKLY', or 'DAILY'";
27 | }
28 |
29 | if (rrule.until) {
30 | if (isNaN(Date.parse(rrule.until))) {
31 | counter += 1
32 | throw "Recurrence rrule 'until' must be a valid date string";
33 | }
34 | }
35 |
36 | if (rrule.interval) {
37 | if (isNaN(parseInt(rrule.interval))) {
38 | counter += 1
39 | throw "Recurrence rrule 'interval' must be an integer";
40 | }
41 | }
42 |
43 | if (rrule.count) {
44 | if (isNaN(parseInt(rrule.count))) {
45 | counter += 1
46 | throw "Recurrence rrule 'count' must be an integer";
47 | }
48 | }
49 |
50 | if (typeof rrule.byday !== 'undefined') {
51 | if ((Object.prototype.toString.call(rrule.byday) !== '[object Array]')) {
52 | counter += 1
53 | throw "Recurrence rrule 'byday' must be an array";
54 | }
55 |
56 | if (rrule.byday.length > 7) {
57 | counter += 1
58 | throw "Recurrence rrule 'byday' array must not be longer than the 7 days in a week";
59 | }
60 |
61 | rrule.byday = rrule.byday.filter(function (elem, pos) {
62 | return rrule.byday.indexOf(elem) == pos;
63 | });
64 |
65 | for (var d in rrule.byday) {
66 | if (BYDAY_VALUES.indexOf(rrule.byday[d]) < 0) {
67 | counter += 1
68 | throw "Recurrence rrule 'byday' values must include only the following: 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'";
69 | }
70 | }
71 | }
72 | return (counter === 0)
73 | }
74 |
75 | /**
76 | * Helper function for appending CRLF at start and end of file according to RFC rules.
77 | * @function
78 | * @param {string} string - iCalendar source string
79 | * @return {string}
80 | */
81 | function addCRLF(string) {
82 | return `\n${string}\n`
83 | }
84 |
85 |
86 | var counter = 0;
87 |
88 | function getUniqueNumber() {
89 | return counter++;
90 | }
91 |
92 | const install = (Vue, options = {uidDomain: 'evildvl', prodId: 'vueICS'}) => {
93 | Vue.prototype.$ics = {
94 | /**
95 | * Add event to the calendar
96 | * @function
97 | * @param {string} language Language in format en-us (default)
98 | * @param {string} subject Subject/Title of event
99 | * @param {string} description Description of event
100 | * @param {string} location Location of event
101 | * @param {string} begin Beginning date of event
102 | * @param {string} stop Ending date of event
103 | * @param {string} url URL
104 | * @param {object} organizer Organizer
105 | * @param {RRule} rrule Reccurence rule
106 | * @returns {string} event
107 | **/
108 |
109 | removeAllEvents: () => {
110 | Events = [];
111 | },
112 | addEvent: (language = 'en-us', subject, description, location = 'none', begin, stop, url = null, organizer = null, rrule = null) => {
113 | let rruleString
114 |
115 | if (typeof subject === 'undefined' ||
116 | typeof description === 'undefined' ||
117 | typeof location === 'undefined' ||
118 | typeof begin === 'undefined' ||
119 | typeof stop === 'undefined') {
120 | throw 'You need to specify function arguments'
121 | }
122 | if (rrule && validateRepeatRule(rrule)) {
123 | rruleString = `RRULE:FREQ=${rrule.freq}`
124 | if (rrule.until) {
125 | let untilDate = new Date(Date.parse(rrule.until)).toISOString();
126 | rruleString += `;UNTIL=${untilDate.substring(0, untilDate.length - 13).replace(/[-]/g, '')}000000Z`
127 | }
128 | if (rrule.interval) rruleString += `;INTERVAL=${rrule.interval}`
129 | if (rrule.count) rruleString += `;COUNT=${rrule.count}`
130 | if (rrule.byday && rrule.byday.length > 0) rruleString += `;BYDAY=${rrule.byday.join(',')}`
131 | }
132 |
133 | let start_date = new Date(begin);
134 | let end_date = new Date(stop);
135 | let now_date = new Date();
136 | const UID = `${now_date.getDay()}${now_date.getMonth()}${now_date.getFullYear()}-${now_date.getHours()}${now_date.getMinutes()}${now_date.getSeconds()}${getUniqueNumber()}`
137 |
138 | let start_year = (`0000${(start_date.getFullYear().toString())}`).slice(-4)
139 | let start_month = (`00${((start_date.getMonth() + 1).toString())}`).slice(-2)
140 | let start_day = (`00${((start_date.getDate()).toString())}`).slice(-2)
141 | let start_hours = (`00${(start_date.getHours().toString())}`).slice(-2)
142 | let start_minutes = (`00${(start_date.getMinutes().toString())}`).slice(-2)
143 | let start_seconds = (`00${(start_date.getSeconds().toString())}`).slice(-2)
144 |
145 | let end_year = (`0000${(end_date.getFullYear().toString())}`).slice(-4)
146 | let end_month = (`00${((end_date.getMonth() + 1).toString())}`).slice(-2)
147 | let end_day = (`00${((end_date.getDate()).toString())}`).slice(-2)
148 | let end_hours = (`00${(end_date.getHours().toString())}`).slice(-2)
149 | let end_minutes = (`00${(end_date.getMinutes().toString())}`).slice(-2)
150 | let end_seconds = (`00${(end_date.getSeconds().toString())}`).slice(-2)
151 |
152 | let now_year = (`0000${(now_date.getFullYear().toString())}`).slice(-4)
153 | let now_month = (`00${((now_date.getMonth() + 1).toString())}`).slice(-2)
154 | let now_day = (`00${((now_date.getDate()).toString())}`).slice(-2)
155 | let now_hours = (`00${(now_date.getHours().toString())}`).slice(-2)
156 | let now_minutes = (`00${(now_date.getMinutes().toString())}`).slice(-2)
157 | let now_seconds = (`00${(now_date.getSeconds().toString())}`).slice(-2)
158 |
159 | let start_time = '';
160 | let end_time = '';
161 | if (start_hours + start_minutes + start_seconds + end_hours + end_minutes + end_seconds != 0) {
162 | start_time = `T${start_hours}${start_minutes}${start_seconds}`
163 | end_time = `T${end_hours}${end_minutes}${end_seconds}`
164 | }
165 | let now_time = `T${now_hours}${now_minutes}${now_seconds}`
166 |
167 | let start = start_year + start_month + start_day + start_time
168 | let end = end_year + end_month + end_day + end_time
169 | let now = now_year + now_month + now_day + now_time
170 |
171 | const Event = `
172 | BEGIN:VEVENT
173 | UID:${UID}@${options.uidDomain}
174 | ${(url) ? 'URL:' + url : ''}
175 | DESCRIPTION:${description}${(rruleString) ? '\n' + rruleString : ''}
176 | DTSTAMP;VALUE=DATE-TIME:${now},
177 | DTSTART;VALUE=DATE-TIME:${start}
178 | DTEND;VALUE=DATE-TIME:${end}
179 | LOCATION:${location}
180 | ${(organizer) ? 'ORGANIZER;CN=' + organizer.name + ':MAILTO:' + organizer.email : ''}
181 | SUMMARY;LANGUAGE=${language}:${subject}
182 | END:VEVENT
183 | `
184 | Events.push(Event)
185 | return Event
186 | },
187 | /**
188 | * Returns calendar
189 | * @function
190 | * @return {string} Calendar in iCalendar format
191 | */
192 | calendar: () => {
193 | return addCRLF(`
194 | BEGIN:VCALENDAR
195 | PRODID:${options.prodId}
196 | VERSION:2.0
197 | ${Events.join('\n')}
198 | END:VCALENDAR
199 |
200 | `.replace(/^\s*[\r\n]/gm, "").replace(/^\s+/gm, ''))
201 | },
202 | /**
203 | * Download iCalendar file
204 | * @function
205 | * @param {string} filename - Name of the file without extension
206 | */
207 | download: (filename) => {
208 | const Calendar = addCRLF(`
209 | BEGIN:VCALENDAR
210 | PRODID:${options.prodId}
211 | VERSION:2.0
212 | ${Events.join('\n')}
213 | END:VCALENDAR
214 |
215 | `.replace(/^\s*[\r\n]/gm, "").replace(/^\s+/gm, ''))
216 | var blob = new Blob([Calendar], {type: "text/x-vCalendar;charset=utf-8"});
217 | saveAs(blob, `${filename}.ics`);
218 | }
219 |
220 | }
221 | }
222 |
223 | const plugin = {
224 | install,
225 | version
226 | }
227 |
228 | export default plugin
229 |
230 | if (typeof window !== 'undefined' && window.Vue) {
231 | window.Vue.use(plugin)
232 | }
233 |
--------------------------------------------------------------------------------
/dist/vue-ics.esm.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-ics v0.1.3
3 | * (c) 2020 Stanislav Mihaylov
4 | * Released under the MIT License.
5 | */
6 | import { saveAs } from 'file-saver';
7 |
8 | var version = '0.1.3';
9 | /**
10 | * Reccurence rule
11 | * @typedef {Object} RRule
12 | * @property {string} freq - Required. The frequency of event recurrence. Can be DAILY, WEEKLY, MONTHLY, or YEARLY.
13 | * @property {string | number | Date} until - date stringA date string representing the date on which to end repitition. Must be friendly to Date()
14 | * @property {number} interval - The interval of freq to recur at. For example, if freq is WEEKLY and interval is 2, the event will repeat every 2 weeks
15 | * @property {array} byday - Which days of the week the event is to occur. An array containing any of SU, MO, TU, WE, TH, FR, SA
16 | */
17 |
18 | var Events = [];
19 | /**
20 | * Reccurence rule validation
21 | * @function
22 | * @param {RRule} rrule - Reccurence rule
23 | * @returns {boolean}
24 | */
25 |
26 | function validateRepeatRule(rrule) {
27 | var counter = 0;
28 | var BYDAY_VALUES = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
29 |
30 | if (rrule.freq !== 'YEARLY' && rrule.freq !== 'MONTHLY' && rrule.freq !== 'WEEKLY' && rrule.freq !== 'DAILY') {
31 | counter += 1;
32 | throw "Recurrence rrule frequency must be provided and be one of the following: 'YEARLY', 'MONTHLY', 'WEEKLY', or 'DAILY'";
33 | }
34 |
35 | if (rrule.until) {
36 | if (isNaN(Date.parse(rrule.until))) {
37 | counter += 1;
38 | throw "Recurrence rrule 'until' must be a valid date string";
39 | }
40 | }
41 |
42 | if (rrule.interval) {
43 | if (isNaN(parseInt(rrule.interval))) {
44 | counter += 1;
45 | throw "Recurrence rrule 'interval' must be an integer";
46 | }
47 | }
48 |
49 | if (rrule.count) {
50 | if (isNaN(parseInt(rrule.count))) {
51 | counter += 1;
52 | throw "Recurrence rrule 'count' must be an integer";
53 | }
54 | }
55 |
56 | if (typeof rrule.byday !== 'undefined') {
57 | if (Object.prototype.toString.call(rrule.byday) !== '[object Array]') {
58 | counter += 1;
59 | throw "Recurrence rrule 'byday' must be an array";
60 | }
61 |
62 | if (rrule.byday.length > 7) {
63 | counter += 1;
64 | throw "Recurrence rrule 'byday' array must not be longer than the 7 days in a week";
65 | }
66 |
67 | rrule.byday = rrule.byday.filter(function (elem, pos) {
68 | return rrule.byday.indexOf(elem) == pos;
69 | });
70 |
71 | for (var d in rrule.byday) {
72 | if (BYDAY_VALUES.indexOf(rrule.byday[d]) < 0) {
73 | counter += 1;
74 | throw "Recurrence rrule 'byday' values must include only the following: 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'";
75 | }
76 | }
77 | }
78 |
79 | return counter === 0;
80 | }
81 | /**
82 | * Helper function for appending CRLF at start and end of file according to RFC rules.
83 | * @function
84 | * @param {string} string - iCalendar source string
85 | * @return {string}
86 | */
87 |
88 |
89 | function addCRLF(string) {
90 | return "\n".concat(string, "\n");
91 | }
92 |
93 | var counter = 0;
94 |
95 | function getUniqueNumber() {
96 | return counter++;
97 | }
98 |
99 | var install = function install(Vue) {
100 | var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
101 | uidDomain: 'evildvl',
102 | prodId: 'vueICS'
103 | };
104 | Vue.prototype.$ics = {
105 | /**
106 | * Add event to the calendar
107 | * @function
108 | * @param {string} language Language in format en-us (default)
109 | * @param {string} subject Subject/Title of event
110 | * @param {string} description Description of event
111 | * @param {string} location Location of event
112 | * @param {string} begin Beginning date of event
113 | * @param {string} stop Ending date of event
114 | * @param {string} url URL
115 | * @param {object} organizer Organizer
116 | * @param {RRule} rrule Reccurence rule
117 | * @returns {string} event
118 | **/
119 | removeAllEvents: function removeAllEvents() {
120 | Events = [];
121 | },
122 | addEvent: function addEvent() {
123 | var language = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'en-us';
124 | var subject = arguments.length > 1 ? arguments[1] : undefined;
125 | var description = arguments.length > 2 ? arguments[2] : undefined;
126 | var location = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'none';
127 | var begin = arguments.length > 4 ? arguments[4] : undefined;
128 | var stop = arguments.length > 5 ? arguments[5] : undefined;
129 | var url = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
130 | var organizer = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;
131 | var rrule = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : null;
132 | var rruleString;
133 |
134 | if (typeof subject === 'undefined' || typeof description === 'undefined' || typeof location === 'undefined' || typeof begin === 'undefined' || typeof stop === 'undefined') {
135 | throw 'You need to specify function arguments';
136 | }
137 |
138 | if (rrule && validateRepeatRule(rrule)) {
139 | rruleString = "RRULE:FREQ=".concat(rrule.freq);
140 |
141 | if (rrule.until) {
142 | var untilDate = new Date(Date.parse(rrule.until)).toISOString();
143 | rruleString += ";UNTIL=".concat(untilDate.substring(0, untilDate.length - 13).replace(/[-]/g, ''), "000000Z");
144 | }
145 |
146 | if (rrule.interval) rruleString += ";INTERVAL=".concat(rrule.interval);
147 | if (rrule.count) rruleString += ";COUNT=".concat(rrule.count);
148 | if (rrule.byday && rrule.byday.length > 0) rruleString += ";BYDAY=".concat(rrule.byday.join(','));
149 | }
150 |
151 | var start_date = new Date(begin);
152 | var end_date = new Date(stop);
153 | var now_date = new Date();
154 | var UID = "".concat(now_date.getDay()).concat(now_date.getMonth()).concat(now_date.getFullYear(), "-").concat(now_date.getHours()).concat(now_date.getMinutes()).concat(now_date.getSeconds()).concat(getUniqueNumber());
155 | var start_year = "0000".concat(start_date.getFullYear().toString()).slice(-4);
156 | var start_month = "00".concat((start_date.getMonth() + 1).toString()).slice(-2);
157 | var start_day = "00".concat(start_date.getDate().toString()).slice(-2);
158 | var start_hours = "00".concat(start_date.getHours().toString()).slice(-2);
159 | var start_minutes = "00".concat(start_date.getMinutes().toString()).slice(-2);
160 | var start_seconds = "00".concat(start_date.getSeconds().toString()).slice(-2);
161 | var end_year = "0000".concat(end_date.getFullYear().toString()).slice(-4);
162 | var end_month = "00".concat((end_date.getMonth() + 1).toString()).slice(-2);
163 | var end_day = "00".concat(end_date.getDate().toString()).slice(-2);
164 | var end_hours = "00".concat(end_date.getHours().toString()).slice(-2);
165 | var end_minutes = "00".concat(end_date.getMinutes().toString()).slice(-2);
166 | var end_seconds = "00".concat(end_date.getSeconds().toString()).slice(-2);
167 | var now_year = "0000".concat(now_date.getFullYear().toString()).slice(-4);
168 | var now_month = "00".concat((now_date.getMonth() + 1).toString()).slice(-2);
169 | var now_day = "00".concat(now_date.getDate().toString()).slice(-2);
170 | var now_hours = "00".concat(now_date.getHours().toString()).slice(-2);
171 | var now_minutes = "00".concat(now_date.getMinutes().toString()).slice(-2);
172 | var now_seconds = "00".concat(now_date.getSeconds().toString()).slice(-2);
173 | var start_time = '';
174 | var end_time = '';
175 |
176 | if (start_hours + start_minutes + start_seconds + end_hours + end_minutes + end_seconds != 0) {
177 | start_time = "T".concat(start_hours).concat(start_minutes).concat(start_seconds);
178 | end_time = "T".concat(end_hours).concat(end_minutes).concat(end_seconds);
179 | }
180 |
181 | var now_time = "T".concat(now_hours).concat(now_minutes).concat(now_seconds);
182 | var start = start_year + start_month + start_day + start_time;
183 | var end = end_year + end_month + end_day + end_time;
184 | var now = now_year + now_month + now_day + now_time;
185 | var Event = "\n BEGIN:VEVENT\n UID:".concat(UID, "@").concat(options.uidDomain, "\n ").concat(url ? 'URL:' + url : '', "\n DESCRIPTION:").concat(description).concat(rruleString ? '\n' + rruleString : '', "\n DTSTAMP;VALUE=DATE-TIME:").concat(now, ",\n DTSTART;VALUE=DATE-TIME:").concat(start, "\n DTEND;VALUE=DATE-TIME:").concat(end, "\n LOCATION:").concat(location, "\n ").concat(organizer ? 'ORGANIZER;CN=' + organizer.name + ':MAILTO:' + organizer.email : '', "\n SUMMARY;LANGUAGE=").concat(language, ":").concat(subject, "\n END:VEVENT\n ");
186 | Events.push(Event);
187 | return Event;
188 | },
189 |
190 | /**
191 | * Returns calendar
192 | * @function
193 | * @return {string} Calendar in iCalendar format
194 | */
195 | calendar: function calendar() {
196 | return addCRLF("\n BEGIN:VCALENDAR\n PRODID:".concat(options.prodId, "\n VERSION:2.0\n ").concat(Events.join('\n'), "\n END:VCALENDAR\n\n ").replace(/^\s*[\r\n]/gm, "").replace(/^\s+/gm, ''));
197 | },
198 |
199 | /**
200 | * Download iCalendar file
201 | * @function
202 | * @param {string} filename - Name of the file without extension
203 | */
204 | download: function download(filename) {
205 | var Calendar = addCRLF("\n BEGIN:VCALENDAR\n PRODID:".concat(options.prodId, "\n VERSION:2.0\n ").concat(Events.join('\n'), "\n END:VCALENDAR\n\n ").replace(/^\s*[\r\n]/gm, "").replace(/^\s+/gm, ''));
206 | var blob = new Blob([Calendar], {
207 | type: "text/x-vCalendar;charset=utf-8"
208 | });
209 | saveAs(blob, "".concat(filename, ".ics"));
210 | }
211 | };
212 | };
213 |
214 | var plugin = {
215 | install: install,
216 | version: version
217 | };
218 |
219 | if (typeof window !== 'undefined' && window.Vue) {
220 | window.Vue.use(plugin);
221 | }
222 |
223 | export default plugin;
224 |
--------------------------------------------------------------------------------
/dist/vue-ics.common.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-ics v0.1.3
3 | * (c) 2020 Stanislav Mihaylov
4 | * Released under the MIT License.
5 | */
6 | 'use strict';
7 |
8 | var fileSaver = require('file-saver');
9 |
10 | var version = '0.1.3';
11 | /**
12 | * Reccurence rule
13 | * @typedef {Object} RRule
14 | * @property {string} freq - Required. The frequency of event recurrence. Can be DAILY, WEEKLY, MONTHLY, or YEARLY.
15 | * @property {string | number | Date} until - date stringA date string representing the date on which to end repitition. Must be friendly to Date()
16 | * @property {number} interval - The interval of freq to recur at. For example, if freq is WEEKLY and interval is 2, the event will repeat every 2 weeks
17 | * @property {array} byday - Which days of the week the event is to occur. An array containing any of SU, MO, TU, WE, TH, FR, SA
18 | */
19 |
20 | var Events = [];
21 | /**
22 | * Reccurence rule validation
23 | * @function
24 | * @param {RRule} rrule - Reccurence rule
25 | * @returns {boolean}
26 | */
27 |
28 | function validateRepeatRule(rrule) {
29 | var counter = 0;
30 | var BYDAY_VALUES = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
31 |
32 | if (rrule.freq !== 'YEARLY' && rrule.freq !== 'MONTHLY' && rrule.freq !== 'WEEKLY' && rrule.freq !== 'DAILY') {
33 | counter += 1;
34 | throw "Recurrence rrule frequency must be provided and be one of the following: 'YEARLY', 'MONTHLY', 'WEEKLY', or 'DAILY'";
35 | }
36 |
37 | if (rrule.until) {
38 | if (isNaN(Date.parse(rrule.until))) {
39 | counter += 1;
40 | throw "Recurrence rrule 'until' must be a valid date string";
41 | }
42 | }
43 |
44 | if (rrule.interval) {
45 | if (isNaN(parseInt(rrule.interval))) {
46 | counter += 1;
47 | throw "Recurrence rrule 'interval' must be an integer";
48 | }
49 | }
50 |
51 | if (rrule.count) {
52 | if (isNaN(parseInt(rrule.count))) {
53 | counter += 1;
54 | throw "Recurrence rrule 'count' must be an integer";
55 | }
56 | }
57 |
58 | if (typeof rrule.byday !== 'undefined') {
59 | if (Object.prototype.toString.call(rrule.byday) !== '[object Array]') {
60 | counter += 1;
61 | throw "Recurrence rrule 'byday' must be an array";
62 | }
63 |
64 | if (rrule.byday.length > 7) {
65 | counter += 1;
66 | throw "Recurrence rrule 'byday' array must not be longer than the 7 days in a week";
67 | }
68 |
69 | rrule.byday = rrule.byday.filter(function (elem, pos) {
70 | return rrule.byday.indexOf(elem) == pos;
71 | });
72 |
73 | for (var d in rrule.byday) {
74 | if (BYDAY_VALUES.indexOf(rrule.byday[d]) < 0) {
75 | counter += 1;
76 | throw "Recurrence rrule 'byday' values must include only the following: 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'";
77 | }
78 | }
79 | }
80 |
81 | return counter === 0;
82 | }
83 | /**
84 | * Helper function for appending CRLF at start and end of file according to RFC rules.
85 | * @function
86 | * @param {string} string - iCalendar source string
87 | * @return {string}
88 | */
89 |
90 |
91 | function addCRLF(string) {
92 | return "\n".concat(string, "\n");
93 | }
94 |
95 | var counter = 0;
96 |
97 | function getUniqueNumber() {
98 | return counter++;
99 | }
100 |
101 | var install = function install(Vue) {
102 | var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
103 | uidDomain: 'evildvl',
104 | prodId: 'vueICS'
105 | };
106 | Vue.prototype.$ics = {
107 | /**
108 | * Add event to the calendar
109 | * @function
110 | * @param {string} language Language in format en-us (default)
111 | * @param {string} subject Subject/Title of event
112 | * @param {string} description Description of event
113 | * @param {string} location Location of event
114 | * @param {string} begin Beginning date of event
115 | * @param {string} stop Ending date of event
116 | * @param {string} url URL
117 | * @param {object} organizer Organizer
118 | * @param {RRule} rrule Reccurence rule
119 | * @returns {string} event
120 | **/
121 | removeAllEvents: function removeAllEvents() {
122 | Events = [];
123 | },
124 | addEvent: function addEvent() {
125 | var language = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'en-us';
126 | var subject = arguments.length > 1 ? arguments[1] : undefined;
127 | var description = arguments.length > 2 ? arguments[2] : undefined;
128 | var location = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'none';
129 | var begin = arguments.length > 4 ? arguments[4] : undefined;
130 | var stop = arguments.length > 5 ? arguments[5] : undefined;
131 | var url = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
132 | var organizer = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;
133 | var rrule = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : null;
134 | var rruleString;
135 |
136 | if (typeof subject === 'undefined' || typeof description === 'undefined' || typeof location === 'undefined' || typeof begin === 'undefined' || typeof stop === 'undefined') {
137 | throw 'You need to specify function arguments';
138 | }
139 |
140 | if (rrule && validateRepeatRule(rrule)) {
141 | rruleString = "RRULE:FREQ=".concat(rrule.freq);
142 |
143 | if (rrule.until) {
144 | var untilDate = new Date(Date.parse(rrule.until)).toISOString();
145 | rruleString += ";UNTIL=".concat(untilDate.substring(0, untilDate.length - 13).replace(/[-]/g, ''), "000000Z");
146 | }
147 |
148 | if (rrule.interval) rruleString += ";INTERVAL=".concat(rrule.interval);
149 | if (rrule.count) rruleString += ";COUNT=".concat(rrule.count);
150 | if (rrule.byday && rrule.byday.length > 0) rruleString += ";BYDAY=".concat(rrule.byday.join(','));
151 | }
152 |
153 | var start_date = new Date(begin);
154 | var end_date = new Date(stop);
155 | var now_date = new Date();
156 | var UID = "".concat(now_date.getDay()).concat(now_date.getMonth()).concat(now_date.getFullYear(), "-").concat(now_date.getHours()).concat(now_date.getMinutes()).concat(now_date.getSeconds()).concat(getUniqueNumber());
157 | var start_year = "0000".concat(start_date.getFullYear().toString()).slice(-4);
158 | var start_month = "00".concat((start_date.getMonth() + 1).toString()).slice(-2);
159 | var start_day = "00".concat(start_date.getDate().toString()).slice(-2);
160 | var start_hours = "00".concat(start_date.getHours().toString()).slice(-2);
161 | var start_minutes = "00".concat(start_date.getMinutes().toString()).slice(-2);
162 | var start_seconds = "00".concat(start_date.getSeconds().toString()).slice(-2);
163 | var end_year = "0000".concat(end_date.getFullYear().toString()).slice(-4);
164 | var end_month = "00".concat((end_date.getMonth() + 1).toString()).slice(-2);
165 | var end_day = "00".concat(end_date.getDate().toString()).slice(-2);
166 | var end_hours = "00".concat(end_date.getHours().toString()).slice(-2);
167 | var end_minutes = "00".concat(end_date.getMinutes().toString()).slice(-2);
168 | var end_seconds = "00".concat(end_date.getSeconds().toString()).slice(-2);
169 | var now_year = "0000".concat(now_date.getFullYear().toString()).slice(-4);
170 | var now_month = "00".concat((now_date.getMonth() + 1).toString()).slice(-2);
171 | var now_day = "00".concat(now_date.getDate().toString()).slice(-2);
172 | var now_hours = "00".concat(now_date.getHours().toString()).slice(-2);
173 | var now_minutes = "00".concat(now_date.getMinutes().toString()).slice(-2);
174 | var now_seconds = "00".concat(now_date.getSeconds().toString()).slice(-2);
175 | var start_time = '';
176 | var end_time = '';
177 |
178 | if (start_hours + start_minutes + start_seconds + end_hours + end_minutes + end_seconds != 0) {
179 | start_time = "T".concat(start_hours).concat(start_minutes).concat(start_seconds);
180 | end_time = "T".concat(end_hours).concat(end_minutes).concat(end_seconds);
181 | }
182 |
183 | var now_time = "T".concat(now_hours).concat(now_minutes).concat(now_seconds);
184 | var start = start_year + start_month + start_day + start_time;
185 | var end = end_year + end_month + end_day + end_time;
186 | var now = now_year + now_month + now_day + now_time;
187 | var Event = "\n BEGIN:VEVENT\n UID:".concat(UID, "@").concat(options.uidDomain, "\n ").concat(url ? 'URL:' + url : '', "\n DESCRIPTION:").concat(description).concat(rruleString ? '\n' + rruleString : '', "\n DTSTAMP;VALUE=DATE-TIME:").concat(now, ",\n DTSTART;VALUE=DATE-TIME:").concat(start, "\n DTEND;VALUE=DATE-TIME:").concat(end, "\n LOCATION:").concat(location, "\n ").concat(organizer ? 'ORGANIZER;CN=' + organizer.name + ':MAILTO:' + organizer.email : '', "\n SUMMARY;LANGUAGE=").concat(language, ":").concat(subject, "\n END:VEVENT\n ");
188 | Events.push(Event);
189 | return Event;
190 | },
191 |
192 | /**
193 | * Returns calendar
194 | * @function
195 | * @return {string} Calendar in iCalendar format
196 | */
197 | calendar: function calendar() {
198 | return addCRLF("\n BEGIN:VCALENDAR\n PRODID:".concat(options.prodId, "\n VERSION:2.0\n ").concat(Events.join('\n'), "\n END:VCALENDAR\n\n ").replace(/^\s*[\r\n]/gm, "").replace(/^\s+/gm, ''));
199 | },
200 |
201 | /**
202 | * Download iCalendar file
203 | * @function
204 | * @param {string} filename - Name of the file without extension
205 | */
206 | download: function download(filename) {
207 | var Calendar = addCRLF("\n BEGIN:VCALENDAR\n PRODID:".concat(options.prodId, "\n VERSION:2.0\n ").concat(Events.join('\n'), "\n END:VCALENDAR\n\n ").replace(/^\s*[\r\n]/gm, "").replace(/^\s+/gm, ''));
208 | var blob = new Blob([Calendar], {
209 | type: "text/x-vCalendar;charset=utf-8"
210 | });
211 | fileSaver.saveAs(blob, "".concat(filename, ".ics"));
212 | }
213 | };
214 | };
215 |
216 | var plugin = {
217 | install: install,
218 | version: version
219 | };
220 |
221 | if (typeof window !== 'undefined' && window.Vue) {
222 | window.Vue.use(plugin);
223 | }
224 |
225 | module.exports = plugin;
226 |
--------------------------------------------------------------------------------
/dist/vue-ics.umd.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * vue-ics v0.1.3
3 | * (c) 2020 Stanislav Mihaylov
4 | * Released under the MIT License.
5 | */
6 | (function (global, factory) {
7 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('file-saver')) :
8 | typeof define === 'function' && define.amd ? define(['file-saver'], factory) :
9 | (global = global || self, global.VueIcs = factory(global.fileSaver));
10 | }(this, function (fileSaver) { 'use strict';
11 |
12 | var version = '0.1.3';
13 | /**
14 | * Reccurence rule
15 | * @typedef {Object} RRule
16 | * @property {string} freq - Required. The frequency of event recurrence. Can be DAILY, WEEKLY, MONTHLY, or YEARLY.
17 | * @property {string | number | Date} until - date stringA date string representing the date on which to end repitition. Must be friendly to Date()
18 | * @property {number} interval - The interval of freq to recur at. For example, if freq is WEEKLY and interval is 2, the event will repeat every 2 weeks
19 | * @property {array} byday - Which days of the week the event is to occur. An array containing any of SU, MO, TU, WE, TH, FR, SA
20 | */
21 |
22 | var Events = [];
23 | /**
24 | * Reccurence rule validation
25 | * @function
26 | * @param {RRule} rrule - Reccurence rule
27 | * @returns {boolean}
28 | */
29 |
30 | function validateRepeatRule(rrule) {
31 | var counter = 0;
32 | var BYDAY_VALUES = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
33 |
34 | if (rrule.freq !== 'YEARLY' && rrule.freq !== 'MONTHLY' && rrule.freq !== 'WEEKLY' && rrule.freq !== 'DAILY') {
35 | counter += 1;
36 | throw "Recurrence rrule frequency must be provided and be one of the following: 'YEARLY', 'MONTHLY', 'WEEKLY', or 'DAILY'";
37 | }
38 |
39 | if (rrule.until) {
40 | if (isNaN(Date.parse(rrule.until))) {
41 | counter += 1;
42 | throw "Recurrence rrule 'until' must be a valid date string";
43 | }
44 | }
45 |
46 | if (rrule.interval) {
47 | if (isNaN(parseInt(rrule.interval))) {
48 | counter += 1;
49 | throw "Recurrence rrule 'interval' must be an integer";
50 | }
51 | }
52 |
53 | if (rrule.count) {
54 | if (isNaN(parseInt(rrule.count))) {
55 | counter += 1;
56 | throw "Recurrence rrule 'count' must be an integer";
57 | }
58 | }
59 |
60 | if (typeof rrule.byday !== 'undefined') {
61 | if (Object.prototype.toString.call(rrule.byday) !== '[object Array]') {
62 | counter += 1;
63 | throw "Recurrence rrule 'byday' must be an array";
64 | }
65 |
66 | if (rrule.byday.length > 7) {
67 | counter += 1;
68 | throw "Recurrence rrule 'byday' array must not be longer than the 7 days in a week";
69 | }
70 |
71 | rrule.byday = rrule.byday.filter(function (elem, pos) {
72 | return rrule.byday.indexOf(elem) == pos;
73 | });
74 |
75 | for (var d in rrule.byday) {
76 | if (BYDAY_VALUES.indexOf(rrule.byday[d]) < 0) {
77 | counter += 1;
78 | throw "Recurrence rrule 'byday' values must include only the following: 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'";
79 | }
80 | }
81 | }
82 |
83 | return counter === 0;
84 | }
85 | /**
86 | * Helper function for appending CRLF at start and end of file according to RFC rules.
87 | * @function
88 | * @param {string} string - iCalendar source string
89 | * @return {string}
90 | */
91 |
92 |
93 | function addCRLF(string) {
94 | return "\n".concat(string, "\n");
95 | }
96 |
97 | var counter = 0;
98 |
99 | function getUniqueNumber() {
100 | return counter++;
101 | }
102 |
103 | var install = function install(Vue) {
104 | var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
105 | uidDomain: 'evildvl',
106 | prodId: 'vueICS'
107 | };
108 | Vue.prototype.$ics = {
109 | /**
110 | * Add event to the calendar
111 | * @function
112 | * @param {string} language Language in format en-us (default)
113 | * @param {string} subject Subject/Title of event
114 | * @param {string} description Description of event
115 | * @param {string} location Location of event
116 | * @param {string} begin Beginning date of event
117 | * @param {string} stop Ending date of event
118 | * @param {string} url URL
119 | * @param {object} organizer Organizer
120 | * @param {RRule} rrule Reccurence rule
121 | * @returns {string} event
122 | **/
123 | removeAllEvents: function removeAllEvents() {
124 | Events = [];
125 | },
126 | addEvent: function addEvent() {
127 | var language = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'en-us';
128 | var subject = arguments.length > 1 ? arguments[1] : undefined;
129 | var description = arguments.length > 2 ? arguments[2] : undefined;
130 | var location = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'none';
131 | var begin = arguments.length > 4 ? arguments[4] : undefined;
132 | var stop = arguments.length > 5 ? arguments[5] : undefined;
133 | var url = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null;
134 | var organizer = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;
135 | var rrule = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : null;
136 | var rruleString;
137 |
138 | if (typeof subject === 'undefined' || typeof description === 'undefined' || typeof location === 'undefined' || typeof begin === 'undefined' || typeof stop === 'undefined') {
139 | throw 'You need to specify function arguments';
140 | }
141 |
142 | if (rrule && validateRepeatRule(rrule)) {
143 | rruleString = "RRULE:FREQ=".concat(rrule.freq);
144 |
145 | if (rrule.until) {
146 | var untilDate = new Date(Date.parse(rrule.until)).toISOString();
147 | rruleString += ";UNTIL=".concat(untilDate.substring(0, untilDate.length - 13).replace(/[-]/g, ''), "000000Z");
148 | }
149 |
150 | if (rrule.interval) rruleString += ";INTERVAL=".concat(rrule.interval);
151 | if (rrule.count) rruleString += ";COUNT=".concat(rrule.count);
152 | if (rrule.byday && rrule.byday.length > 0) rruleString += ";BYDAY=".concat(rrule.byday.join(','));
153 | }
154 |
155 | var start_date = new Date(begin);
156 | var end_date = new Date(stop);
157 | var now_date = new Date();
158 | var UID = "".concat(now_date.getDay()).concat(now_date.getMonth()).concat(now_date.getFullYear(), "-").concat(now_date.getHours()).concat(now_date.getMinutes()).concat(now_date.getSeconds()).concat(getUniqueNumber());
159 | var start_year = "0000".concat(start_date.getFullYear().toString()).slice(-4);
160 | var start_month = "00".concat((start_date.getMonth() + 1).toString()).slice(-2);
161 | var start_day = "00".concat(start_date.getDate().toString()).slice(-2);
162 | var start_hours = "00".concat(start_date.getHours().toString()).slice(-2);
163 | var start_minutes = "00".concat(start_date.getMinutes().toString()).slice(-2);
164 | var start_seconds = "00".concat(start_date.getSeconds().toString()).slice(-2);
165 | var end_year = "0000".concat(end_date.getFullYear().toString()).slice(-4);
166 | var end_month = "00".concat((end_date.getMonth() + 1).toString()).slice(-2);
167 | var end_day = "00".concat(end_date.getDate().toString()).slice(-2);
168 | var end_hours = "00".concat(end_date.getHours().toString()).slice(-2);
169 | var end_minutes = "00".concat(end_date.getMinutes().toString()).slice(-2);
170 | var end_seconds = "00".concat(end_date.getSeconds().toString()).slice(-2);
171 | var now_year = "0000".concat(now_date.getFullYear().toString()).slice(-4);
172 | var now_month = "00".concat((now_date.getMonth() + 1).toString()).slice(-2);
173 | var now_day = "00".concat(now_date.getDate().toString()).slice(-2);
174 | var now_hours = "00".concat(now_date.getHours().toString()).slice(-2);
175 | var now_minutes = "00".concat(now_date.getMinutes().toString()).slice(-2);
176 | var now_seconds = "00".concat(now_date.getSeconds().toString()).slice(-2);
177 | var start_time = '';
178 | var end_time = '';
179 |
180 | if (start_hours + start_minutes + start_seconds + end_hours + end_minutes + end_seconds != 0) {
181 | start_time = "T".concat(start_hours).concat(start_minutes).concat(start_seconds);
182 | end_time = "T".concat(end_hours).concat(end_minutes).concat(end_seconds);
183 | }
184 |
185 | var now_time = "T".concat(now_hours).concat(now_minutes).concat(now_seconds);
186 | var start = start_year + start_month + start_day + start_time;
187 | var end = end_year + end_month + end_day + end_time;
188 | var now = now_year + now_month + now_day + now_time;
189 | var Event = "\n BEGIN:VEVENT\n UID:".concat(UID, "@").concat(options.uidDomain, "\n ").concat(url ? 'URL:' + url : '', "\n DESCRIPTION:").concat(description).concat(rruleString ? '\n' + rruleString : '', "\n DTSTAMP;VALUE=DATE-TIME:").concat(now, ",\n DTSTART;VALUE=DATE-TIME:").concat(start, "\n DTEND;VALUE=DATE-TIME:").concat(end, "\n LOCATION:").concat(location, "\n ").concat(organizer ? 'ORGANIZER;CN=' + organizer.name + ':MAILTO:' + organizer.email : '', "\n SUMMARY;LANGUAGE=").concat(language, ":").concat(subject, "\n END:VEVENT\n ");
190 | Events.push(Event);
191 | return Event;
192 | },
193 |
194 | /**
195 | * Returns calendar
196 | * @function
197 | * @return {string} Calendar in iCalendar format
198 | */
199 | calendar: function calendar() {
200 | return addCRLF("\n BEGIN:VCALENDAR\n PRODID:".concat(options.prodId, "\n VERSION:2.0\n ").concat(Events.join('\n'), "\n END:VCALENDAR\n\n ").replace(/^\s*[\r\n]/gm, "").replace(/^\s+/gm, ''));
201 | },
202 |
203 | /**
204 | * Download iCalendar file
205 | * @function
206 | * @param {string} filename - Name of the file without extension
207 | */
208 | download: function download(filename) {
209 | var Calendar = addCRLF("\n BEGIN:VCALENDAR\n PRODID:".concat(options.prodId, "\n VERSION:2.0\n ").concat(Events.join('\n'), "\n END:VCALENDAR\n\n ").replace(/^\s*[\r\n]/gm, "").replace(/^\s+/gm, ''));
210 | var blob = new Blob([Calendar], {
211 | type: "text/x-vCalendar;charset=utf-8"
212 | });
213 | fileSaver.saveAs(blob, "".concat(filename, ".ics"));
214 | }
215 | };
216 | };
217 |
218 | var plugin = {
219 | install: install,
220 | version: version
221 | };
222 |
223 | if (typeof window !== 'undefined' && window.Vue) {
224 | window.Vue.use(plugin);
225 | }
226 |
227 | return plugin;
228 |
229 | }));
230 |
--------------------------------------------------------------------------------