Repository: AnandChowdhary/calendar-link Branch: master Commit: 4f703c983797 Files: 23 Total size: 70.7 KB Directory structure: gitextract_1s7uubm_/ ├── .github/ │ ├── dependabot.yml │ ├── labeler.yml │ └── workflows/ │ ├── node.yml │ ├── release-scheduler.yml │ ├── stale.yml │ └── test.yml ├── .gitignore ├── .npmignore ├── .prettierrc.cjs ├── CHANGELOG.md ├── LICENSE ├── README.md ├── _config.yml ├── jest-global-setup.js ├── jest.config.js ├── package.json ├── release.config.js ├── src/ │ ├── __snapshots__/ │ │ └── index.spec.ts.snap │ ├── index.spec.ts │ ├── index.ts │ ├── interfaces.ts │ └── utils.ts └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: "npm" directory: "/" schedule: interval: "daily" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" ================================================ FILE: .github/labeler.yml ================================================ config: - ./* tooling: - tooling/**/*.* assets: - static/**/*.* tests: - any: ["src/**/*.spec.js", "cypress/**/*"] package: - any: ["package.json", "package-lock.json"] source: - src/**/* ================================================ FILE: .github/workflows/node.yml ================================================ name: Node CI on: push: branches: - master workflow_dispatch: jobs: release: name: Build, test, and release runs-on: ubuntu-latest if: "!contains(github.event.head_commit.message, '[skip ci]')" steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 16 - name: Cache node modules uses: actions/cache@v4 env: cache-name: cache-node-modules with: path: ~/.npm key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-build-${{ env.cache-name }}- ${{ runner.os }}-build- ${{ runner.os }}- - name: Install dependencies run: npm ci - name: Build TypeScript run: npm run build - name: Release run: npx semantic-release env: GITHUB_TOKEN: ${{ secrets.GH_PAT }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} GIT_AUTHOR_NAME: "Koj Bot" GIT_AUTHOR_EMAIL: "bot@koj.co" GIT_COMMITTER_NAME: "Koj Bot" GIT_COMMITTER_EMAIL: "bot@koj.co" ================================================ FILE: .github/workflows/release-scheduler.yml ================================================ name: Release Scheduler CI on: schedule: - cron: "0 0 * * 1" workflow_dispatch: jobs: releaseScheduler: runs-on: ubuntu-latest steps: - name: Run release-scheduler uses: koj-co/release-scheduler@master env: GH_PAT: ${{ secrets.GH_PAT }} ================================================ FILE: .github/workflows/stale.yml ================================================ name: "Stale Issues CI" on: schedule: - cron: "0 0 * * *" jobs: stale: runs-on: ubuntu-latest steps: - uses: actions/stale@v9 with: repo-token: ${{ secrets.GH_PAT }} stale-issue-message: "⚠️ This issue has not seen any activity in the past 2 months so I'm marking it as stale. I'll close it if it doesn't see any activity in the coming week." stale-pr-message: "⚠️ This PR has not seen any activity in the past 2 months so I'm marking it as stale. I'll close it if it doesn't see any activity in the coming week." days-before-stale: 60 days-before-close: 7 stale-issue-label: "wontfix" exempt-issue-labels: "wip" stale-pr-label: "wontfix" exempt-pr-labels: "wip" ================================================ FILE: .github/workflows/test.yml ================================================ name: Test CI on: push: branches-ignore: - master jobs: release: name: Build and test runs-on: ubuntu-18.04 if: "!contains(github.event.head_commit.message, '[skip ci]')" steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 16 - name: Install dependencies run: npm ci - name: Build TypeScript run: npm run build ================================================ FILE: .gitignore ================================================ node_modules coverage .nyc_output .DS_Store *.log .vscode .idea compiled .awcache .rpt2_cache dist/ ================================================ FILE: .npmignore ================================================ .vscode .licenses .github ================================================ FILE: .prettierrc.cjs ================================================ module.exports = require("@koj/config").prettier; ================================================ FILE: CHANGELOG.md ================================================ ## v2.11.0 (2025-06-20) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.11.0) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.10.0...v2.11.0) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.11.0) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.11.0.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.11.0.tar.gz)) ### ✨ New features - [`f1863f6`](https://github.com/AnandChowdhary/calendar-link/commit/f1863f6) Support adding guests for outlook (#648) (Issues: [`#648`](https://github.com/AnandChowdhary/calendar-link/issues/648)) ## v2.10.0 (2025-05-20) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.10.0) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.9.0...v2.10.0) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.10.0) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.10.0.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.10.0.tar.gz)) ### ✨ New features - [`a9581ed`](https://github.com/AnandChowdhary/calendar-link/commit/a9581ed) Add support for ICS file's UID field ## v2.9.0 (2025-05-19) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.9.0) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.8.0...v2.9.0) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.9.0) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.9.0.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.9.0.tar.gz)) ### ✨ New features - [`dfd7975`](https://github.com/AnandChowdhary/calendar-link/commit/dfd7975) Set ics PRODID correctly (#621) (Issues: [`#621`](https://github.com/AnandChowdhary/calendar-link/issues/621)) ### 🐛 Bug fixes - [`194118a`](https://github.com/AnandChowdhary/calendar-link/commit/194118a) Events without end should not necessarily end "now" (#622) (Issues: [`#622`](https://github.com/AnandChowdhary/calendar-link/issues/622)) ### ⬆️ Dependency updates - [`dd4bc49`](https://github.com/AnandChowdhary/calendar-link/commit/dd4bc49) Upgrade dependencies and workflows for improved CI performance ## v2.8.0 (2024-12-23) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.8.0) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.7.0...v2.8.0) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.8.0) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.8.0.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.8.0.tar.gz)) ### ✨ New features - [`581db9f`](https://github.com/AnandChowdhary/calendar-link/commit/581db9f) Add status X-MICROSOFT for allDay support ## v2.7.0 (2024-07-31) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.7.0) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.6.1...v2.7.0) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.7.0) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.7.0.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.7.0.tar.gz)) ### ✨ New features - [`003905a`](https://github.com/AnandChowdhary/calendar-link/commit/003905a) Add Microsoft Teams Calendar Event Generation Feature (#604) (Issues: [`#604`](https://github.com/AnandChowdhary/calendar-link/issues/604)) ## v2.6.1 (2024-07-31) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.6.1) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.6.0...v2.6.1) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.6.1) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.6.1.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.6.1.tar.gz)) ### 🐛 Bug fixes - [`6da873c`](https://github.com/AnandChowdhary/calendar-link/commit/6da873c) Fix Snapshot Tests for ICS Links (#600) (Issues: [`#600`](https://github.com/AnandChowdhary/calendar-link/issues/600)) ## v2.6.0 (2023-09-29) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.6.0) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.5.1...v2.6.0) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.6.0) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.6.0.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.6.0.tar.gz)) ### ✨ New features - [`2d2067f`](https://github.com/AnandChowdhary/calendar-link/commit/2d2067f) Trigger release manually ## v2.5.1 (2023-07-19) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.5.1) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.5.0...v2.5.1) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.5.1) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.5.1.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.5.1.tar.gz)) ### 🐛 Bug fixes - [`e4a2eaa`](https://github.com/AnandChowdhary/calendar-link/commit/e4a2eaa) Fix ICS file generation with CLRF and absent fields (#553) (Issues: [`#553`](https://github.com/AnandChowdhary/calendar-link/issues/553)) ## v2.5.0 (2023-07-12) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.5.0) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.4.0...v2.5.0) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.5.0) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.5.0.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.5.0.tar.gz)) ### ✨ New features - [`4828504`](https://github.com/AnandChowdhary/calendar-link/commit/4828504) Use ubuntu-latest for CI - [`0ac72d5`](https://github.com/AnandChowdhary/calendar-link/commit/0ac72d5) Release new version ## v2.4.0 (2022-10-21) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.4.0) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.3.1...v2.4.0) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.4.0) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.4.0.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.4.0.tar.gz)) ### ✨ New features - [`9b3efb4`](https://github.com/AnandChowdhary/calendar-link/commit/9b3efb4) Add support for local time in Outlook and Office365 ### ⬆️ Dependency updates - [`4d551e8`](https://github.com/AnandChowdhary/calendar-link/commit/4d551e8) Bump parse-path from 4.0.2 to 7.0.0 (#488) (Issues: [`#488`](https://github.com/AnandChowdhary/calendar-link/issues/488))- [`dc0df9e`](https://github.com/AnandChowdhary/calendar-link/commit/dc0df9e) Bump actions/setup-node from 2.1.5 to 3.5.1 (#486) (Issues: [`#486`](https://github.com/AnandChowdhary/calendar-link/issues/486))- [`da3fa08`](https://github.com/AnandChowdhary/calendar-link/commit/da3fa08) Bump actions/checkout from 2.3.4 to 3.1.0 (#485) (Issues: [`#485`](https://github.com/AnandChowdhary/calendar-link/issues/485))- [`6756c4b`](https://github.com/AnandChowdhary/calendar-link/commit/6756c4b) Bump typescript from 4.2.3 to 4.8.4 (#481) (Issues: [`#481`](https://github.com/AnandChowdhary/calendar-link/issues/481))- [`c184373`](https://github.com/AnandChowdhary/calendar-link/commit/c184373) Bump actions/stale from 3 to 6 (#478) (Issues: [`#478`](https://github.com/AnandChowdhary/calendar-link/issues/478))- [`7ea8657`](https://github.com/AnandChowdhary/calendar-link/commit/7ea8657) Bump ansi-regex, ansi-regex and ansi-regex (#490) (Issues: [`#490`](https://github.com/AnandChowdhary/calendar-link/issues/490))- [`5755074`](https://github.com/AnandChowdhary/calendar-link/commit/5755074) Bump actions/cache from 2 to 3.0.11 (#493) (Issues: [`#493`](https://github.com/AnandChowdhary/calendar-link/issues/493)) ## v2.3.1 (2022-10-20) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.3.1) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.3.0...v2.3.1) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.3.1) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.3.1.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.3.1.tar.gz)) ### 🐛 Bug fixes - [`339e6e4`](https://github.com/AnandChowdhary/calendar-link/commit/339e6e4) missing RRULE prefix for google (#489) (Issues: [`#489`](https://github.com/AnandChowdhary/calendar-link/issues/489)) ## v2.3.0 (2022-10-19) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.3.0) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.2.0...v2.3.0) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.3.0) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.3.0.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.3.0.tar.gz)) ### ✨ New features - [`2ce44b7`](https://github.com/AnandChowdhary/calendar-link/commit/2ce44b7) Recurring events ## v2.2.0 (2022-05-16) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.2.0) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.1.1...v2.2.0) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.2.0) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.2.0.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.2.0.tar.gz)) ### ✨ New features - [`87f3aa7`](https://github.com/AnandChowdhary/calendar-link/commit/87f3aa7) Trigger new release ## v2.1.1 (2021-04-16) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.1.1) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.1.0...v2.1.1) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.1.1) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.1.1.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.1.1.tar.gz)) ### 🐛 Bug fixes - [`7ff87dc`](https://github.com/AnandChowdhary/calendar-link/commit/7ff87dc) Add docs for units (fixed #286) (Issues: [`#286`](https://github.com/AnandChowdhary/calendar-link/issues/286)) ## v2.1.0 (2021-04-15) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.1.0) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.16...v2.1.0) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.1.0) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.1.0.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.1.0.tar.gz)) ### ✨ New features - [`376ae97`](https://github.com/AnandChowdhary/calendar-link/commit/376ae97) Deploy new UMD/ES modules ## v2.0.16 (2021-03-08) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.16) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.15...v2.0.16) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.16) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.16.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.16.tar.gz)) ### ⬆️ Dependency updates - [`c1741d1`](https://github.com/AnandChowdhary/calendar-link/commit/c1741d1) Bump query-string from 6.14.0 to 6.14.1 - [`7cb3493`](https://github.com/AnandChowdhary/calendar-link/commit/7cb3493) Bump semantic-release from 17.4.0 to 17.4.1 - [`22a79d2`](https://github.com/AnandChowdhary/calendar-link/commit/22a79d2) Bump typescript from 4.2.2 to 4.2.3 - [`a6bfe2a`](https://github.com/AnandChowdhary/calendar-link/commit/a6bfe2a) Bump ts-jest from 26.5.2 to 26.5.3 ## v2.0.15 (2021-03-01) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.15) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.14...v2.0.15) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.15) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.15.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.15.tar.gz)) ### ⬆️ Dependency updates - [`4dc96f3`](https://github.com/AnandChowdhary/calendar-link/commit/4dc96f3) Bump actions/setup-node from v2.1.4 to v2.1.5 - [`74e463b`](https://github.com/AnandChowdhary/calendar-link/commit/74e463b) Bump typescript from 4.1.5 to 4.2.2 - [`cd9e252`](https://github.com/AnandChowdhary/calendar-link/commit/cd9e252) Bump ts-jest from 26.5.1 to 26.5.2 - [`e1fc524`](https://github.com/AnandChowdhary/calendar-link/commit/e1fc524) Bump semantic-release from 17.3.9 to 17.4.0 ## v2.0.14 (2021-02-22) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.14) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.13...v2.0.14) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.14) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.14.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.14.tar.gz)) ### ⬆️ Dependency updates - [`bffd4aa`](https://github.com/AnandChowdhary/calendar-link/commit/bffd4aa) Bump semantic-release from 17.3.8 to 17.3.9 - [`654d5eb`](https://github.com/AnandChowdhary/calendar-link/commit/654d5eb) Bump vsoch/pull-request-action from 1.0.13 to 1.0.14 - [`3f28822`](https://github.com/AnandChowdhary/calendar-link/commit/3f28822) Bump pascalgn/automerge-action from v0.13.0 to v0.13.1 - [`dbd5da9`](https://github.com/AnandChowdhary/calendar-link/commit/dbd5da9) Bump vsoch/pull-request-action from 1.0.14 to 1.0.15 ## v2.0.13 (2021-02-15) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.13) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.12...v2.0.13) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.13) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.13.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.13.tar.gz)) ### ⬆️ Dependency updates - [`e78919b`](https://github.com/AnandChowdhary/calendar-link/commit/e78919b) Bump semantic-release from 17.3.7 to 17.3.8 - [`e3f8340`](https://github.com/AnandChowdhary/calendar-link/commit/e3f8340) Bump ts-jest from 26.5.0 to 26.5.1 - [`8eaf178`](https://github.com/AnandChowdhary/calendar-link/commit/8eaf178) Bump typescript from 4.1.3 to 4.1.4 - [`d00ae83`](https://github.com/AnandChowdhary/calendar-link/commit/d00ae83) Bump query-string from 6.13.8 to 6.14.0 - [`e86754a`](https://github.com/AnandChowdhary/calendar-link/commit/e86754a) Bump typescript from 4.1.4 to 4.1.5 ## v2.0.12 (2021-02-08) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.12) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.11...v2.0.12) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.12) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.12.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.12.tar.gz)) ### ⬆️ Dependency updates - [`e0e9942`](https://github.com/AnandChowdhary/calendar-link/commit/e0e9942) Bump ts-jest from 26.4.4 to 26.5.0 ## v2.0.11 (2021-02-01) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.11) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.10...v2.0.11) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.11) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.11.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.11.tar.gz)) ### ⬆️ Dependency updates - [`7d1d848`](https://github.com/AnandChowdhary/calendar-link/commit/7d1d848) Bump dayjs from 1.10.3 to 1.10.4 - [`20c87ca`](https://github.com/AnandChowdhary/calendar-link/commit/20c87ca) Bump semantic-release from 17.3.6 to 17.3.7 ## v2.0.10 (2021-01-25) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.10) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.9...v2.0.10) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.10) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.10.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.10.tar.gz)) ### ⬆️ Dependency updates - [`98bd892`](https://github.com/AnandChowdhary/calendar-link/commit/98bd892) Bump semantic-release from 17.3.2 to 17.3.3 - [`927646c`](https://github.com/AnandChowdhary/calendar-link/commit/927646c) Bump @semantic-release/npm from 7.0.9 to 7.0.10 - [`57d7bc3`](https://github.com/AnandChowdhary/calendar-link/commit/57d7bc3) Bump semantic-release from 17.3.3 to 17.3.4 - [`08299b8`](https://github.com/AnandChowdhary/calendar-link/commit/08299b8) Bump semantic-release from 17.3.4 to 17.3.6 ## v2.0.9 (2021-01-18) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.9) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.8...v2.0.9) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.9) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.9.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.9.tar.gz)) ### ⬆️ Dependency updates - [`f4a33a7`](https://github.com/AnandChowdhary/calendar-link/commit/f4a33a7) Bump dayjs from 1.10.2 to 1.10.3 - [`c593b68`](https://github.com/AnandChowdhary/calendar-link/commit/c593b68) Bump semantic-release from 17.3.1 to 17.3.2 ## v2.0.8 (2021-01-11) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.8) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.7...v2.0.8) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.8) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.8.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.8.tar.gz)) ### ⬆️ Dependency updates - [`70dccdb`](https://github.com/AnandChowdhary/calendar-link/commit/70dccdb) Bump dayjs from 1.9.8 to 1.10.1 - [`cefc6f3`](https://github.com/AnandChowdhary/calendar-link/commit/cefc6f3) Bump dayjs from 1.10.1 to 1.10.2 - [`b38bb28`](https://github.com/AnandChowdhary/calendar-link/commit/b38bb28) Bump @types/jest from 26.0.19 to 26.0.20 ## v2.0.7 (2021-01-04) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.7) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.6...v2.0.7) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.7) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.7.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.7.tar.gz)) ### ⬆️ Dependency updates - [`9ea5f1f`](https://github.com/AnandChowdhary/calendar-link/commit/9ea5f1f) Bump dayjs from 1.9.7 to 1.9.8 - [`57deca6`](https://github.com/AnandChowdhary/calendar-link/commit/57deca6) Bump semantic-release from 17.3.0 to 17.3.1 - [`d309356`](https://github.com/AnandChowdhary/calendar-link/commit/d309356) Bump query-string from 6.13.7 to 6.13.8 ## v2.0.6 (2020-12-28) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.6) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.5...v2.0.6) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.6) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.6.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.6.tar.gz)) ### ⬆️ Dependency updates - [`96a46eb`](https://github.com/AnandChowdhary/calendar-link/commit/96a46eb) Bump vsoch/pull-request-action from 1.0.12 to 1.0.13 - [`afabdce`](https://github.com/AnandChowdhary/calendar-link/commit/afabdce) Bump pascalgn/automerge-action from v0.12.0 to v0.13.0 ## v2.0.5 (2020-12-21) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.5) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.4...v2.0.5) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.5) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.5.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.5.tar.gz)) ### ⬆️ Dependency updates - [`03b581f`](https://github.com/AnandChowdhary/calendar-link/commit/03b581f) Bump typescript from 4.1.2 to 4.1.3 - [`5a098e5`](https://github.com/AnandChowdhary/calendar-link/commit/5a098e5) Bump actions/setup-node from v2.1.3 to v2.1.4 ## v2.0.4 (2020-12-14) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.4) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.3...v2.0.4) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.4) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.4.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.4.tar.gz)) ### ⬆️ Dependency updates - [`454f6d5`](https://github.com/AnandChowdhary/calendar-link/commit/454f6d5) Bump dayjs from 1.9.6 to 1.9.7 - [`d658954`](https://github.com/AnandChowdhary/calendar-link/commit/d658954) Bump @types/jest from 26.0.16 to 26.0.17 - [`e89c536`](https://github.com/AnandChowdhary/calendar-link/commit/e89c536) Bump @types/jest from 26.0.17 to 26.0.18 - [`d75c79b`](https://github.com/AnandChowdhary/calendar-link/commit/d75c79b) Bump @types/jest from 26.0.18 to 26.0.19 - [`3f5cb35`](https://github.com/AnandChowdhary/calendar-link/commit/3f5cb35) Bump actions/setup-node from v2.1.2 to v2.1.3 - [`ac8f283`](https://github.com/AnandChowdhary/calendar-link/commit/ac8f283) Bump ini from 1.3.5 to 1.3.7 ## v2.0.3 (2020-12-07) [📝 Release notes](https://github.com/AnandChowdhary/calendar-link/releases/tag/v2.0.3) · [💻 Compare](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.2...v2.0.3) · [🔖 Tag](https://github.com/AnandChowdhary/calendar-link/tree/v2.0.3) · 🗄️ Archive ([zip](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.3.zip) · [tar.gz](https://github.com/AnandChowdhary/calendar-link/archive/v2.0.3.tar.gz)) ### ⬆️ Dependency updates - [`5f507d8`](https://github.com/AnandChowdhary/calendar-link/commit/5f507d8) Bump @types/jest from 26.0.15 to 26.0.16 - [`db9f07d`](https://github.com/AnandChowdhary/calendar-link/commit/db9f07d) Bump @koj/config from 1.2.9 to 1.2.11 - [`2a1a283`](https://github.com/AnandChowdhary/calendar-link/commit/2a1a283) Bump @semantic-release/npm from 7.0.8 to 7.0.9 ## [v2.0.2](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.1...v2.0.2) (2020-11-30) ### ⬆️ Dependency updates - [`066b3dd`](https://github.com/AnandChowdhary/calendar-link/commit/066b3dd) Bump semantic-release from 17.2.4 to 17.3.0 ## [v2.0.1](https://github.com/AnandChowdhary/calendar-link/compare/v2.0.0...v2.0.1) (2020-11-23) ### ⬆️ Dependency updates - [`7666634`](https://github.com/AnandChowdhary/calendar-link/commit/7666634) Bump query-string from 6.13.5 to 6.13.6 - [`925ba7f`](https://github.com/AnandChowdhary/calendar-link/commit/925ba7f) Bump jest from 26.5.3 to 26.6.0 - [`a06c6ed`](https://github.com/AnandChowdhary/calendar-link/commit/a06c6ed) Bump @types/jest from 26.0.14 to 26.0.15 - [`f130e0d`](https://github.com/AnandChowdhary/calendar-link/commit/f130e0d) Bump vsoch/pull-request-action from 1.0.10 to 1.0.11 - [`fb33dd2`](https://github.com/AnandChowdhary/calendar-link/commit/fb33dd2) Bump jest from 26.6.0 to 26.6.1 - [`43a869a`](https://github.com/AnandChowdhary/calendar-link/commit/43a869a) Bump dayjs from 1.9.3 to 1.9.4 - [`d602964`](https://github.com/AnandChowdhary/calendar-link/commit/d602964) Bump ts-jest from 26.4.1 to 26.4.3 - [`4f4b551`](https://github.com/AnandChowdhary/calendar-link/commit/4f4b551) Bump typescript from 4.0.3 to 4.0.5 - [`38cdadf`](https://github.com/AnandChowdhary/calendar-link/commit/38cdadf) Bump @koj/config from 1.2.5 to 1.2.6 - [`e88438c`](https://github.com/AnandChowdhary/calendar-link/commit/e88438c) Bump @koj/config from 1.2.6 to 1.2.7 - [`b146cd7`](https://github.com/AnandChowdhary/calendar-link/commit/b146cd7) Bump semantic-release from 17.2.1 to 17.2.2 - [`156dbe1`](https://github.com/AnandChowdhary/calendar-link/commit/156dbe1) Bump jest from 26.6.1 to 26.6.2 - [`7b20e30`](https://github.com/AnandChowdhary/calendar-link/commit/7b20e30) Bump actions/checkout from v2.3.3 to v2.3.4 - [`9a4e975`](https://github.com/AnandChowdhary/calendar-link/commit/9a4e975) Bump @koj/config from 1.2.7 to 1.2.8 - [`912ecac`](https://github.com/AnandChowdhary/calendar-link/commit/912ecac) Bump jest from 26.6.2 to 26.6.3 - [`49cd32b`](https://github.com/AnandChowdhary/calendar-link/commit/49cd32b) Bump query-string from 6.13.6 to 6.13.7 - [`4dd597e`](https://github.com/AnandChowdhary/calendar-link/commit/4dd597e) Bump dayjs from 1.9.4 to 1.9.5 - [`ecb28b0`](https://github.com/AnandChowdhary/calendar-link/commit/ecb28b0) Bump ts-jest from 26.4.3 to 26.4.4 - [`88da0d7`](https://github.com/AnandChowdhary/calendar-link/commit/88da0d7) Bump dayjs from 1.9.5 to 1.9.6 - [`4490ea7`](https://github.com/AnandChowdhary/calendar-link/commit/4490ea7) Bump @semantic-release/github from 7.1.1 to 7.1.2 - [`d959618`](https://github.com/AnandChowdhary/calendar-link/commit/d959618) Bump semantic-release from 17.2.2 to 17.2.3 - [`47a61d2`](https://github.com/AnandChowdhary/calendar-link/commit/47a61d2) Bump @semantic-release/npm from 7.0.6 to 7.0.8 - [`fc6a455`](https://github.com/AnandChowdhary/calendar-link/commit/fc6a455) Bump @koj/config from 1.2.8 to 1.2.9 - [`b7ffeb5`](https://github.com/AnandChowdhary/calendar-link/commit/b7ffeb5) Bump @semantic-release/github from 7.1.2 to 7.2.0 - [`e0e599a`](https://github.com/AnandChowdhary/calendar-link/commit/e0e599a) Update koj-co/template - [`7a5e25c`](https://github.com/AnandChowdhary/calendar-link/commit/7a5e25c) Bump semantic-release from 17.2.3 to 17.2.4 - [`237d0a4`](https://github.com/AnandChowdhary/calendar-link/commit/237d0a4) Bump typescript from 4.0.5 to 4.1.2 # [v2.0.0](https://github.com/AnandChowdhary/calendar-link/compare/v1.0.0...v2.0.0) (2020-10-17) ## 💥 Breaking changes - [`008de9a`](https://github.com/AnandChowdhary/calendar-link/commit/008de9a) Trigger major release # v1.0.0 (2020-10-17) ## ✨ New features - [`5fb280f`](https://github.com/AnandChowdhary/calendar-link/commit/5fb280f) Add Google link generator - [`c1b3875`](https://github.com/AnandChowdhary/calendar-link/commit/c1b3875) Add Outlook and Yahoo! Calendar - [`d10afa6`](https://github.com/AnandChowdhary/calendar-link/commit/d10afa6) Add all day events & improve timezone handling - [`34e70d3`](https://github.com/AnandChowdhary/calendar-link/commit/34e70d3) Allow all day events spanning multiple days - [`6f820e1`](https://github.com/AnandChowdhary/calendar-link/commit/6f820e1) Trigger major release ## ♻️ Updates - [`793ac2e`](https://github.com/AnandChowdhary/calendar-link/commit/793ac2e) Use query-string instead of querystring ## 🐛 Bug fixes - [`f01579b`](https://github.com/AnandChowdhary/calendar-link/commit/f01579b) Use new Outlook URL ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2019 Anand Chowdhary Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # 📅 Calendar Link | | Status | | - | - | | Build | ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/AnandChowdhary/calendar-link/node.yml) [![Dependencies](https://img.shields.io/librariesio/github/AnandChowdhary/calendar-link)](https://libraries.io/github/AnandChowdhary/calendar-link) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/AnandChowdhary/calendar-link)](https://github.com/AnandChowdhary/calendar-link/releases) | | Health | [![License](https://img.shields.io/github/license/anandchowdhary/calendar-link.svg)](https://github.com/AnandChowdhary/calendar-link/blob/master/LICENSE) [![Coverage](https://img.shields.io/coveralls/github/AnandChowdhary/calendar-link)](https://coveralls.io/github/AnandChowdhary/calendar-link) | | Community | ![NPM type definitions](https://img.shields.io/npm/types/calendar-link.svg) [![NPM](https://img.shields.io/npm/v/calendar-link.svg)](https://www.npmjs.com/package/calendar-link) ![GitHub contributors](https://img.shields.io/github/contributors/AnandChowdhary/calendar-link) | JavaScript library to generate an event link for Google Calendar, Yahoo! Calendar, Microsoft Outlook, etc. [![NPM](https://nodei.co/npm/calendar-link.png)](https://npm.im/calendar-link/) ### Usage ```js // Usage with Node.js const { google, outlook, office365, yahoo, ics } = require("calendar-link"); // Usage with TypeScript or ES6 import { google, outlook, office365, yahoo, ics } from "calendar-link"; // Set event as an object const event = { uid: "your-unqiue-id", title: "My birthday party", description: "Be there!", start: "2019-12-29 18:00:00 +0100", duration: [3, "hour"], }; // Then fetch the link google(event); // https://calendar.google.com/calendar/render... outlook(event); // https://outlook.live.com/owa/... office365(event); // https://outlook.office.com/owa/... yahoo(event); // https://calendar.yahoo.com/?v=60&title=... ics(event); // standard ICS file based on https://icalendar.org ``` ### Options | Property | Description | Allowed values | | ------------------ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | `title` (required) | Event title | String | | `start` (required) | Start time | JS Date / ISO 8601 string / Unix Timestamp | | `end` | End time | JS Date / ISO 8601 string / Unix Timestamp | | `duration` | Event duration | Array with value (Number) and unit (String) | | `allDay` | All day event | Boolean | | `rRule` | Recurring event | iCal [recurrence rule](https://www.rfc-editor.org/rfc/rfc5545#section-3.3.10) string
**NOTE:** Only supported by `google` and `ics` | | `description` | Information about the event | String | | `location` | Event location in words | String | | `busy` | Mark on calendar as busy? | Boolean | | `guests` | Emails of other guests. This is currently only supported for `google`, `outlook`, `outlookMobile`, `office365`, `office365Mobile` and `msTeams` | Array of emails (String) | | `url` | Calendar document URL | String | | `uid` | Unique identifier for the event | String | #### Notes - Any one of the fields `end`, `duration`, or `allDay` is required. - The allowed units in `duration` are listed here: https://day.js.org/docs/en/durations/creating#list-of-all-available-units. - The `url` field defaults to `document.URL` if a global `document` object exists. For server-side rendering, you should supply the `url` manually. - Not all calendars support the `guests` and `url` fields. For `guests` support in outlook/office calendar, this has been tested with `outlook` and `office365` [when this PR was implemented](https://github.com/AnandChowdhary/calendar-link/pull/648) but we weren't able to test this with `outlookMobile` and `office365Mobile` so it might not work as expected. However, all outlook/office calendar links have same path and query string structure so we just added them as even if the query string is invalid, it will just be ignored and won't break anything. - If you don't pass the start and end time in UTC, Google will convert it to UTC but Outlook won't, so it's a good idea to use UTC when passing dates and times - There are some known issues in Office 365 because of which we can't generate a consistent link in all devices (#542) - The `uid` field is currently optional and will generate a random ID if not provided. In a future version, this field will be required to ensure proper event identification and deduplication. ## Compatibility This package uses [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) (Node.js >= 10, 97%+ browsers), but if you need to include a polyfill, you can include [url-search-params-polyfill](https://www.npmjs.com/package/url-search-params-polyfill) first. ## License MIT © [Anand Chowdhary](https://anandchowdhary.com/?utm_source=github&utm_medium=calendar-link&utm_campaign=readme) ================================================ FILE: _config.yml ================================================ theme: jekyll-theme-minimal ================================================ FILE: jest-global-setup.js ================================================ module.exports = async () => { process.env.TZ = "UTC"; }; ================================================ FILE: jest.config.js ================================================ module.exports = { preset: "ts-jest", globalSetup: "./jest-global-setup.js", testEnvironment: "node", watchPathIgnorePatterns: ['node_modules'], }; ================================================ FILE: package.json ================================================ { "name": "calendar-link", "version": "2.11.0", "description": "📅 Calendar link generator for popular services, like Google, Outlook, and Yahoo.", "main": "dist/index.js", "types": "dist/index.d.ts", "source": "src/index.ts", "exports": { ".": { "import": "./dist/index.modern.mjs", "require": "./dist/index.js", "types": "./dist/index.d.ts" } }, "umd:main": "dist/index.umd.js", "files": [ "dist" ], "scripts": { "build:umd": "microbundle --external none --format modern,umd", "build:cjs": "tsc -m commonjs", "build": "run-p build:*", "test": "jest", "test-watch": "jest --watch", "coverage": "jest --coverage", "update-template": "npx update-template https://github.com/AnandChowdhary/calendar-link", "semantic-release": "semantic-release" }, "repository": { "type": "git", "url": "git+https://github.com/AnandChowdhary/calendar-link.git" }, "keywords": [ "nodejs", "typescript", "calendar", "calendar-link", "google-calendar", "outlook", "yahoo" ], "author": "Anand Chowdhary ", "license": "MIT", "bugs": { "url": "https://github.com/AnandChowdhary/calendar-link/issues" }, "homepage": "https://anandchowdhary.github.io/calendar-link/", "devDependencies": { "@koj/config": "1.2.11", "@semantic-release/changelog": "^5.0.1", "@semantic-release/git": "^9.0.0", "@semantic-release/github": "^7.1.1", "@semantic-release/npm": "^7.0.6", "@types/jest": "^26.0.14", "jest": "^26.6.0", "microbundle": "^0.15.1", "npm-run-all": "^4.1.5", "semantic-release": "^17.2.1", "semantic-release-gitmoji": "^1.3.4", "ts-jest": "^26.4.1", "typescript": "^4.0.3" }, "dependencies": { "dayjs": "^1.9.3" } } ================================================ FILE: release.config.js ================================================ module.exports = require("@koj/config").releaseMaster; ================================================ FILE: src/__snapshots__/index.spec.ts.snap ================================================ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`aol service generate a aol link 1`] = `"https://calendar.aol.com/?dur=false&et=20191229T020000Z&st=20191229T000000Z&title=Birthday%20party&v=60"`; exports[`aol service generate a aol link with description 1`] = `"https://calendar.aol.com/?desc=Bring%20gifts%21&dur=false&et=20191229T020000Z&st=20191229T000000Z&title=Birthday%20party&v=60"`; exports[`aol service generate a aol link with guests 1`] = `"https://calendar.aol.com/?dur=false&et=20191229T020000Z&st=20191229T000000Z&title=Birthday%20party&v=60"`; exports[`aol service generate a aol link with time & timezone 1`] = `"https://calendar.aol.com/?dur=false&et=20191229T130000Z&st=20191229T110000Z&title=Birthday%20party&v=60"`; exports[`aol service generate a multi day aol link 1`] = `"https://calendar.aol.com/?dur=allday&et=20200112&st=20191229&title=Birthday%20party&v=60"`; exports[`aol service generate a recurring aol link 1`] = `"https://calendar.aol.com/?dur=false&et=20191229T020000Z&st=20191229T000000Z&title=Birthday%20party&v=60"`; exports[`aol service generate an all day aol link 1`] = `"https://calendar.aol.com/?dur=allday&et=20191230&st=20191229&title=Birthday%20party&v=60"`; exports[`google service generate a google link 1`] = `"https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20191229T000000Z%2F20191229T020000Z&text=Birthday%20party"`; exports[`google service generate a google link with description 1`] = `"https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20191229T000000Z%2F20191229T020000Z&details=Bring%20gifts%21&text=Birthday%20party"`; exports[`google service generate a google link with guests 1`] = `"https://calendar.google.com/calendar/render?action=TEMPLATE&add=hello%40example.com%2Canother%40example.com&dates=20191229T000000Z%2F20191229T020000Z&text=Birthday%20party"`; exports[`google service generate a google link with time & timezone 1`] = `"https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20191229T110000Z%2F20191229T130000Z&text=Birthday%20party"`; exports[`google service generate a multi day google link 1`] = `"https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20191229%2F20200112&text=Birthday%20party"`; exports[`google service generate a recurring google link 1`] = `"https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20191229T000000Z%2F20191229T020000Z&recur=RRULE%3AFREQ%3DYEARLY%3BINTERVAL%3D1&text=Birthday%20party"`; exports[`google service generate an all day google link 1`] = `"https://calendar.google.com/calendar/render?action=TEMPLATE&dates=20191229%2F20191230&text=Birthday%20party"`; exports[`ics service generate a ics link 1`] = `"data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0D%0AVERSION:2.0%0D%0APRODID:-%2F%2FAnandChowdhary%2F%2Fcalendar-link%2F%2FEN%0D%0ABEGIN:VEVENT%0D%0ADTSTART:20191229T000000Z%0D%0ADTEND:20191229T020000Z%0D%0ADTSTAMP:20191228T120000Z%0D%0ASUMMARY:Birthday%20party%0D%0AUID:12345%0D%0AEND:VEVENT%0D%0AEND:VCALENDAR%0D%0A"`; exports[`ics service generate a ics link with description 1`] = `"data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0D%0AVERSION:2.0%0D%0APRODID:-%2F%2FAnandChowdhary%2F%2Fcalendar-link%2F%2FEN%0D%0ABEGIN:VEVENT%0D%0ADTSTART:20191229T000000Z%0D%0ADTEND:20191229T020000Z%0D%0ADTSTAMP:20191228T120000Z%0D%0ASUMMARY:Birthday%20party%0D%0ADESCRIPTION:Bring%20gifts!%0D%0AUID:12345%0D%0AEND:VEVENT%0D%0AEND:VCALENDAR%0D%0A"`; exports[`ics service generate a ics link with guests 1`] = `"data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0D%0AVERSION:2.0%0D%0APRODID:-%2F%2FAnandChowdhary%2F%2Fcalendar-link%2F%2FEN%0D%0ABEGIN:VEVENT%0D%0ADTSTART:20191229T000000Z%0D%0ADTEND:20191229T020000Z%0D%0ADTSTAMP:20191228T120000Z%0D%0ASUMMARY:Birthday%20party%0D%0AUID:12345%0D%0AEND:VEVENT%0D%0AEND:VCALENDAR%0D%0A"`; exports[`ics service generate a ics link with time & timezone 1`] = `"data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0D%0AVERSION:2.0%0D%0APRODID:-%2F%2FAnandChowdhary%2F%2Fcalendar-link%2F%2FEN%0D%0ABEGIN:VEVENT%0D%0ADTSTART:20191229T110000Z%0D%0ADTEND:20191229T130000Z%0D%0ADTSTAMP:20191228T120000Z%0D%0ASUMMARY:Birthday%20party%0D%0AUID:12345%0D%0AEND:VEVENT%0D%0AEND:VCALENDAR%0D%0A"`; exports[`ics service generate a ics link with uid 1`] = `"data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0D%0AVERSION:2.0%0D%0APRODID:-%2F%2FAnandChowdhary%2F%2Fcalendar-link%2F%2FEN%0D%0ABEGIN:VEVENT%0D%0ADTSTART:20191229T000000Z%0D%0ADTEND:20191229T020000Z%0D%0ADTSTAMP:20191228T120000Z%0D%0ASUMMARY:Birthday%20party%0D%0AUID:abc_123%0D%0AEND:VEVENT%0D%0AEND:VCALENDAR%0D%0A"`; exports[`ics service generate a multi day ics link 1`] = `"data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0D%0AVERSION:2.0%0D%0APRODID:-%2F%2FAnandChowdhary%2F%2Fcalendar-link%2F%2FEN%0D%0ABEGIN:VEVENT%0D%0ADTSTART:20191229%0D%0ADTEND:20200112%0D%0ADTSTAMP:20191228T120000Z%0D%0AX-MICROSOFT-CDO-ALLDAYEVENT:TRUE%0D%0AX-MICROSOFT-MSNCALENDAR-ALLDAYEVENT:TRUE%0D%0ASUMMARY:Birthday%20party%0D%0AUID:12345%0D%0AEND:VEVENT%0D%0AEND:VCALENDAR%0D%0A"`; exports[`ics service generate a recurring ics link 1`] = `"data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0D%0AVERSION:2.0%0D%0APRODID:-%2F%2FAnandChowdhary%2F%2Fcalendar-link%2F%2FEN%0D%0ABEGIN:VEVENT%0D%0ADTSTART:20191229T000000Z%0D%0ADTEND:20191229T020000Z%0D%0ADTSTAMP:20191228T120000Z%0D%0ARRULE:FREQ%3DYEARLY%3BINTERVAL%3D1%0D%0ASUMMARY:Birthday%20party%0D%0AUID:12345%0D%0AEND:VEVENT%0D%0AEND:VCALENDAR%0D%0A"`; exports[`ics service generate an all day ics link 1`] = `"data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0D%0AVERSION:2.0%0D%0APRODID:-%2F%2FAnandChowdhary%2F%2Fcalendar-link%2F%2FEN%0D%0ABEGIN:VEVENT%0D%0ADTSTART:20191229%0D%0ADTEND:20191230%0D%0ADTSTAMP:20191228T120000Z%0D%0AX-MICROSOFT-CDO-ALLDAYEVENT:TRUE%0D%0AX-MICROSOFT-MSNCALENDAR-ALLDAYEVENT:TRUE%0D%0ASUMMARY:Birthday%20party%0D%0ASTATUS:CONFIRMED%0D%0AUID:12345%0D%0AEND:VEVENT%0D%0AEND:VCALENDAR%0D%0A"`; exports[`msTeams service generate a msTeams link 1`] = `"https://teams.microsoft.com/l/meeting/new?endTime=2019-12-29T02%3A00%3A00.000Z&startTime=2019-12-29T00%3A00%3A00.000Z&subject=Birthday%20party"`; exports[`msTeams service generate a msTeams link with description 1`] = `"https://teams.microsoft.com/l/meeting/new?content=Bring%20gifts%21&endTime=2019-12-29T02%3A00%3A00.000Z&startTime=2019-12-29T00%3A00%3A00.000Z&subject=Birthday%20party"`; exports[`msTeams service generate a msTeams link with guests 1`] = `"https://teams.microsoft.com/l/meeting/new?attendees=hello%40example.com%2Canother%40example.com&endTime=2019-12-29T02%3A00%3A00.000Z&startTime=2019-12-29T00%3A00%3A00.000Z&subject=Birthday%20party"`; exports[`msTeams service generate a msTeams link with time & timezone 1`] = `"https://teams.microsoft.com/l/meeting/new?endTime=2019-12-29T13%3A00%3A00.000Z&startTime=2019-12-29T11%3A00%3A00.000Z&subject=Birthday%20party"`; exports[`msTeams service generate a multi day msTeams link 1`] = `"https://teams.microsoft.com/l/meeting/new?endTime=2020-01-12T00%3A00%3A00.000Z&startTime=2019-12-29T00%3A00%3A00.000Z&subject=Birthday%20party"`; exports[`msTeams service generate a recurring msTeams link 1`] = `"https://teams.microsoft.com/l/meeting/new?endTime=2019-12-29T02%3A00%3A00.000Z&startTime=2019-12-29T00%3A00%3A00.000Z&subject=Birthday%20party"`; exports[`msTeams service generate an all day msTeams link 1`] = `"https://teams.microsoft.com/l/meeting/new?endTime=2019-12-30T00%3A00%3A00.000Z&startTime=2019-12-29T00%3A00%3A00.000Z&subject=Birthday%20party"`; exports[`office365 service generate a multi day office365 link 1`] = `"https://outlook.office.com/calendar/0/action/compose?allday=true&enddt=2020-01-12T00%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`office365 service generate a office365 link 1`] = `"https://outlook.office.com/calendar/0/action/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`office365 service generate a office365 link with description 1`] = `"https://outlook.office.com/calendar/0/action/compose?allday=false&body=Bring%20gifts%21&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`office365 service generate a office365 link with guests 1`] = `"https://outlook.office.com/calendar/0/action/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party&to=hello%40example.com%2Canother%40example.com"`; exports[`office365 service generate a office365 link with time & timezone 1`] = `"https://outlook.office.com/calendar/0/action/compose?allday=false&enddt=2019-12-29T13%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T11%3A00%3A00&subject=Birthday%20party"`; exports[`office365 service generate a recurring office365 link 1`] = `"https://outlook.office.com/calendar/0/action/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`office365 service generate an all day office365 link 1`] = `"https://outlook.office.com/calendar/0/action/compose?allday=true&enddt=2019-12-30T00%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`office365Mobile service generate a multi day office365Mobile link 1`] = `"https://outlook.office.com/calendar/0/deeplink/compose?allday=true&enddt=2020-01-12T00%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`office365Mobile service generate a office365Mobile link 1`] = `"https://outlook.office.com/calendar/0/deeplink/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`office365Mobile service generate a office365Mobile link with description 1`] = `"https://outlook.office.com/calendar/0/deeplink/compose?allday=false&body=Bring%20gifts%21&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`office365Mobile service generate a office365Mobile link with guests 1`] = `"https://outlook.office.com/calendar/0/deeplink/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party&to=hello%40example.com%2Canother%40example.com"`; exports[`office365Mobile service generate a office365Mobile link with time & timezone 1`] = `"https://outlook.office.com/calendar/0/deeplink/compose?allday=false&enddt=2019-12-29T13%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T11%3A00%3A00&subject=Birthday%20party"`; exports[`office365Mobile service generate a recurring office365Mobile link 1`] = `"https://outlook.office.com/calendar/0/deeplink/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`office365Mobile service generate an all day office365Mobile link 1`] = `"https://outlook.office.com/calendar/0/deeplink/compose?allday=true&enddt=2019-12-30T00%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`outlook service generate a multi day outlook link 1`] = `"https://outlook.live.com/calendar/0/action/compose?allday=true&enddt=2020-01-12T00%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`outlook service generate a outlook link 1`] = `"https://outlook.live.com/calendar/0/action/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`outlook service generate a outlook link with description 1`] = `"https://outlook.live.com/calendar/0/action/compose?allday=false&body=Bring%20gifts%21&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`outlook service generate a outlook link with guests 1`] = `"https://outlook.live.com/calendar/0/action/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party&to=hello%40example.com%2Canother%40example.com"`; exports[`outlook service generate a outlook link with time & timezone 1`] = `"https://outlook.live.com/calendar/0/action/compose?allday=false&enddt=2019-12-29T13%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T11%3A00%3A00&subject=Birthday%20party"`; exports[`outlook service generate a recurring outlook link 1`] = `"https://outlook.live.com/calendar/0/action/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`outlook service generate an all day outlook link 1`] = `"https://outlook.live.com/calendar/0/action/compose?allday=true&enddt=2019-12-30T00%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`outlookMobile service generate a multi day outlookMobile link 1`] = `"https://outlook.live.com/calendar/0/deeplink/compose?allday=true&enddt=2020-01-12T00%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`outlookMobile service generate a outlookMobile link 1`] = `"https://outlook.live.com/calendar/0/deeplink/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`outlookMobile service generate a outlookMobile link with description 1`] = `"https://outlook.live.com/calendar/0/deeplink/compose?allday=false&body=Bring%20gifts%21&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`outlookMobile service generate a outlookMobile link with guests 1`] = `"https://outlook.live.com/calendar/0/deeplink/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party&to=hello%40example.com%2Canother%40example.com"`; exports[`outlookMobile service generate a outlookMobile link with time & timezone 1`] = `"https://outlook.live.com/calendar/0/deeplink/compose?allday=false&enddt=2019-12-29T13%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T11%3A00%3A00&subject=Birthday%20party"`; exports[`outlookMobile service generate a recurring outlookMobile link 1`] = `"https://outlook.live.com/calendar/0/deeplink/compose?allday=false&enddt=2019-12-29T02%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`outlookMobile service generate an all day outlookMobile link 1`] = `"https://outlook.live.com/calendar/0/deeplink/compose?allday=true&enddt=2019-12-30T00%3A00%3A00&path=%2Fcalendar%2Faction%2Fcompose&rru=addevent&startdt=2019-12-29T00%3A00%3A00&subject=Birthday%20party"`; exports[`yahoo service generate a multi day yahoo link 1`] = `"https://calendar.yahoo.com/?dur=allday&et=20200112&st=20191229&title=Birthday%20party&v=60"`; exports[`yahoo service generate a recurring yahoo link 1`] = `"https://calendar.yahoo.com/?dur=false&et=20191229T020000Z&st=20191229T000000Z&title=Birthday%20party&v=60"`; exports[`yahoo service generate a yahoo link 1`] = `"https://calendar.yahoo.com/?dur=false&et=20191229T020000Z&st=20191229T000000Z&title=Birthday%20party&v=60"`; exports[`yahoo service generate a yahoo link with description 1`] = `"https://calendar.yahoo.com/?desc=Bring%20gifts%21&dur=false&et=20191229T020000Z&st=20191229T000000Z&title=Birthday%20party&v=60"`; exports[`yahoo service generate a yahoo link with guests 1`] = `"https://calendar.yahoo.com/?dur=false&et=20191229T020000Z&st=20191229T000000Z&title=Birthday%20party&v=60"`; exports[`yahoo service generate a yahoo link with time & timezone 1`] = `"https://calendar.yahoo.com/?dur=false&et=20191229T130000Z&st=20191229T110000Z&title=Birthday%20party&v=60"`; exports[`yahoo service generate an all day yahoo link 1`] = `"https://calendar.yahoo.com/?dur=allday&et=20191230&st=20191229&title=Birthday%20party&v=60"`; ================================================ FILE: src/index.spec.ts ================================================ import { aol, google, ics, msTeams, office365, office365Mobile, outlook, outlookMobile, yahoo, } from "./index"; import { CalendarEvent } from "./interfaces"; for (const service of [ aol, google, ics, msTeams, office365, office365Mobile, outlook, outlookMobile, yahoo, ]) { beforeAll(() => { jest.useFakeTimers("modern"); jest.setSystemTime(new Date("2019-12-28T12:00:00.000Z")); jest.spyOn(global.Math, "random").mockReturnValue(0.12345); }); afterAll(() => { jest.useRealTimers(); }); describe(`${service.name} service`, () => { test(`generate a ${service.name} link`, () => { const event: CalendarEvent = { title: "Birthday party", start: "2019-12-29", duration: [2, "hour"], }; const link = service(event); expect(link).toMatchSnapshot(); }); test(`generate a ${service.name} link with description`, () => { const event: CalendarEvent = { title: "Birthday party", start: "2019-12-29", duration: [2, "hour"], description: "Bring gifts!", }; const link = service(event); expect(link).toMatchSnapshot(); }); test(`generate a ${service.name} link with time & timezone`, () => { const event: CalendarEvent = { title: "Birthday party", start: "2019-12-29T12:00:00.000+01:00", duration: [2, "hour"], }; const link = service(event); expect(link).toMatchSnapshot(); }); test(`generate an all day ${service.name} link`, () => { const event: CalendarEvent = { title: "Birthday party", start: "2019-12-29", allDay: true, status: "CONFIRMED", }; const link = service(event); expect(link).toMatchSnapshot(); }); test(`generate a multi day ${service.name} link`, () => { const event: CalendarEvent = { title: "Birthday party", start: "2019-12-29", end: "2020-01-12", allDay: true, }; const link = service(event); expect(link).toMatchSnapshot(); }); test(`generate a recurring ${service.name} link`, () => { const event: CalendarEvent = { title: "Birthday party", start: "2019-12-29", duration: [2, "hour"], rRule: "FREQ=YEARLY;INTERVAL=1", }; const link = service(event); expect(link).toMatchSnapshot(); }); test(`generate a ${service.name} link with guests`, () => { const event: CalendarEvent = { title: "Birthday party", start: "2019-12-29", duration: [2, "hour"], guests: ["hello@example.com", "another@example.com"], }; const link = service(event); expect(link).toMatchSnapshot(); }); if (service.name === ics.name) { test(`generate a ${service.name} link with uid`, () => { const event: CalendarEvent = { title: "Birthday party", start: "2019-12-29", duration: [2, "hour"], uid: 'abc_123' }; const link = service(event); expect(link).toMatchSnapshot(); }); } }); } ================================================ FILE: src/index.ts ================================================ import dayjs from "dayjs"; import utc from "dayjs/plugin/utc"; import { CalendarEvent, CalendarEventOrganizer, NormalizedCalendarEvent, Aol, Google, MsTeams, Outlook, Yahoo, } from "./interfaces"; import { TimeFormats } from "./utils"; dayjs.extend(utc); function stringify(input: Record): string { const params = new URLSearchParams(); Object.keys(input) .sort() .forEach((key) => { const value = input[key]; if (value != null) { params.append(key, value); } }); return params.toString().replace(/\+/g, "%20"); } function formatTimes( { startTime, endTime }: NormalizedCalendarEvent, dateTimeFormat: keyof typeof TimeFormats ): { start: string; end: string } { const format = TimeFormats[dateTimeFormat]; return { start: startTime.format(format), end: endTime.format(format) }; } export const eventify = (event: CalendarEvent, toUtc: boolean = true): NormalizedCalendarEvent => { const { start, end, duration, ...rest } = event; const startTime = toUtc ? dayjs(start).utc() : dayjs(start); const endTime = end ? toUtc ? dayjs(end).utc() : dayjs(end) : (() => { if (event.allDay) { return startTime.add(1, "day"); } if (duration && duration.length == 2) { const value = Number(duration[0]); const unit = duration[1]; return startTime.add(value, unit); } return startTime; })(); return { ...rest, startTime: startTime, endTime: endTime, }; }; export const google = (calendarEvent: CalendarEvent): string => { const event = eventify(calendarEvent); const { start, end } = formatTimes(event, event.allDay ? "allDay" : "dateTimeUTC"); const details: Google = { action: "TEMPLATE", text: event.title, details: event.description, location: event.location, trp: event.busy, dates: start + "/" + end, recur: event.rRule ? "RRULE:" + event.rRule : undefined, }; if (event.guests && event.guests.length) { details.add = event.guests.join(); } return `https://calendar.google.com/calendar/render?${stringify(details)}`; }; export const outlook = (calendarEvent: CalendarEvent): string => { const event = eventify(calendarEvent, false); const { start, end } = formatTimes(event, "dateTimeLocal"); const details: Outlook = { path: "/calendar/action/compose", rru: "addevent", startdt: start, enddt: end, subject: event.title, body: event.description, location: event.location, allday: event.allDay || false, }; if (event.guests && event.guests.length) { details.to = event.guests.join(); } return `https://outlook.live.com/calendar/0/action/compose?${stringify(details)}`; }; export const outlookMobile = (calendarEvent: CalendarEvent): string => { const event = eventify(calendarEvent, false); const { start, end } = formatTimes(event, "dateTimeLocal"); const details: Outlook = { path: "/calendar/action/compose", rru: "addevent", startdt: start, enddt: end, subject: event.title, body: event.description, location: event.location, allday: event.allDay || false, }; if (event.guests && event.guests.length) { details.to = event.guests.join(); } return `https://outlook.live.com/calendar/0/deeplink/compose?${stringify(details)}`; }; export const office365 = (calendarEvent: CalendarEvent): string => { const event = eventify(calendarEvent, false); const { start, end } = formatTimes(event, "dateTimeLocal"); const details: Outlook = { path: "/calendar/action/compose", rru: "addevent", startdt: start, enddt: end, subject: event.title, body: event.description, location: event.location, allday: event.allDay || false, }; if (event.guests && event.guests.length) { details.to = event.guests.join(); } return `https://outlook.office.com/calendar/0/action/compose?${stringify(details)}`; }; export const office365Mobile = (calendarEvent: CalendarEvent): string => { const event = eventify(calendarEvent, false); const { start, end } = formatTimes(event, "dateTimeLocal"); const details: Outlook = { path: "/calendar/action/compose", rru: "addevent", startdt: start, enddt: end, subject: event.title, body: event.description, location: event.location, allday: event.allDay || false, }; if (event.guests && event.guests.length) { details.to = event.guests.join(); } return `https://outlook.office.com/calendar/0/deeplink/compose?${stringify(details)}`; }; export const yahoo = (calendarEvent: CalendarEvent): string => { const event = eventify(calendarEvent); const { start, end } = formatTimes(event, event.allDay ? "allDay" : "dateTimeUTC"); const details: Yahoo = { v: 60, title: event.title, st: start, et: end, desc: event.description, in_loc: event.location, dur: event.allDay ? "allday" : false, }; return `https://calendar.yahoo.com/?${stringify(details)}`; }; export const aol = (calendarEvent: CalendarEvent): string => { const event = eventify(calendarEvent); const { start, end } = formatTimes(event, event.allDay ? "allDay" : "dateTimeUTC"); const details: Aol = { v: 60, title: event.title, st: start, et: end, desc: event.description, in_loc: event.location, dur: event.allDay ? "allday" : false, }; return `https://calendar.aol.com/?${stringify(details)}`; }; // https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/deep-link-workflow?tabs=teamsjs-v2#configure-deep-link-manually-to-open-a-meeting-scheduling-dialog export const msTeams = (calendarEvent: CalendarEvent): string => { const event = eventify(calendarEvent); const details: MsTeams = { subject: event.title, content: event.description, startTime: event.startTime.toISOString(), endTime: event.endTime.toISOString(), }; if (event.guests && event.guests.length) { details.attendees = event.guests.join(); } return `https://teams.microsoft.com/l/meeting/new?${stringify(details)}`; }; export const ics = (calendarEvent: CalendarEvent): string => { const event = eventify(calendarEvent); const formattedDescription: string = (event.description || "") .replace(/,/gm, ",") .replace(/;/gm, ";") .replace(/\r\n/gm, "\n") .replace(/\n/gm, "\\n") .replace(/(\\n)[\s\t]+/gm, "\\n"); const formattedLocation: string = (event.location || "") .replace(/,/gm, ",") .replace(/;/gm, ";") .replace(/\r\n/gm, "\n") .replace(/\n/gm, "\\n") .replace(/(\\n)[\s\t]+/gm, "\\n"); const { start, end } = formatTimes(event, event.allDay ? "allDay" : "dateTimeUTC"); const dateStamp = dayjs(new Date()).utc().format(TimeFormats["dateTimeUTC"]); const calendarChunks = [ { key: "BEGIN", value: "VCALENDAR", }, { key: "VERSION", value: "2.0", }, { key: "PRODID", value: "-//AnandChowdhary//calendar-link//EN" }, { key: "BEGIN", value: "VEVENT", }, { key: "URL", value: event.url, }, { key: "DTSTART", value: start, }, { key: "DTEND", value: end, }, { key: "DTSTAMP", value: dateStamp, }, ...(event.allDay ? [ { key: "X-MICROSOFT-CDO-ALLDAYEVENT", value: "TRUE" }, { key: "X-MICROSOFT-MSNCALENDAR-ALLDAYEVENT", value: "TRUE" }] : []), { key: "RRULE", value: event.rRule, }, { key: "SUMMARY", value: event.title, }, { key: "DESCRIPTION", value: formattedDescription, }, { key: "LOCATION", value: formattedLocation, }, { key: "ORGANIZER", value: event.organizer, }, { key: "STATUS", value: event.status, }, { key: "UID", value: event.uid || Math.floor(Math.random() * 100000).toString().replace(".", ""), }, { key: "END", value: "VEVENT", }, { key: "END", value: "VCALENDAR", }, ]; let calendarUrl: string = ""; calendarChunks.forEach((chunk) => { if (chunk.value) { if (chunk.key == "ORGANIZER") { const value = chunk.value as CalendarEventOrganizer; calendarUrl += `${chunk.key};${encodeURIComponent( `CN=${value.name}:MAILTO:${value.email}\r\n` )}`; } else { calendarUrl += `${chunk.key}:${encodeURIComponent(`${chunk.value}\r\n`)}`; } } }); return `data:text/calendar;charset=utf8,${calendarUrl}`; }; export { CalendarEvent }; ================================================ FILE: src/interfaces.ts ================================================ import * as dayjs from "dayjs"; interface CalendarEvent { title: string; start: any; end?: any; duration?: [number, dayjs.UnitType]; allDay?: boolean; rRule?: string; description?: string; location?: string; organizer?: CalendarEventOrganizer; busy?: boolean; guests?: string[]; url?: string; status?: 'CONFIRMED' | 'TENTATIVE' | 'CANCELLED'; uid?: string; } interface CalendarEventOrganizer { name: string; email: string; } interface NormalizedCalendarEvent extends Omit { startTime: dayjs.Dayjs; endTime: dayjs.Dayjs; } interface Google extends Record { action: string; text: string; dates: string; details?: string; location?: string; trp?: boolean; sprop?: string; add?: string; src?: string; recur?: string; } interface Outlook extends Record { path: string; rru: string; startdt: string; enddt: string; subject: string; allday?: boolean; body?: string; location?: string; to?: string; } interface Yahoo extends Record { v: number; title: string; st: string; et: string; desc?: string; in_loc?: string; } interface Aol extends Record { v: number; title: string; st: string; et: string; desc?: string; in_loc?: string; } interface MsTeams extends Record { subject?: string; content?: string; startTime?: string; endTime?: string; attendees?: string; } export { CalendarEvent, CalendarEventOrganizer, NormalizedCalendarEvent, Outlook, Yahoo, Google, Aol, MsTeams }; ================================================ FILE: src/utils.ts ================================================ export const TimeFormats = { dateTimeLocal: "YYYY-MM-DD[T]HH:mm:ss", dateTimeUTC: "YYYYMMDD[T]HHmmss[Z]", allDay: "YYYYMMDD", }; ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "moduleResolution": "node", "target": "esnext", "module": "esnext", "lib": ["dom", "esnext"], "strict": true, "sourceMap": true, "declaration": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, "declarationDir": "./dist", "outDir": "./dist", "typeRoots": ["node_modules/@types", "@types"] }, "include": ["src", "tooling"], "exclude": ["node_modules"] }