├── .github ├── FUNDING.yml └── workflows │ └── release.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── esbuild.config.mjs ├── example └── email-block-plugin.gif ├── main.ts ├── manifest.json ├── package.json ├── styles.css ├── tsconfig.json └── versions.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: "joleaf" -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Obsidian Plugin 2 | on: 3 | push: 4 | tags: 5 | - '*' 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | with: 12 | fetch-depth: 0 # otherwise, you will failed to push refs to dest repo 13 | - name: Use Node.js 14 | uses: actions/setup-node@v1 15 | with: 16 | node-version: '18.x' 17 | - name: Get Version 18 | id: version 19 | run: | 20 | echo "::set-output name=tag::$(git describe --abbrev=0)" 21 | # Build the plugin 22 | - name: Build 23 | id: build 24 | run: | 25 | npm install 26 | npm run build --if-present 27 | # Package the required files into a zip 28 | - name: Package 29 | run: | 30 | mkdir ${{ github.event.repository.name }} 31 | cp main.js manifest.json README.md styles.css ${{ github.event.repository.name }} 32 | zip -r ${{ github.event.repository.name }}.zip ${{ github.event.repository.name }} 33 | # Create the release on github 34 | - name: Create Release 35 | id: create_release 36 | uses: actions/create-release@v1 37 | env: 38 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 39 | VERSION: ${{ github.ref }} 40 | with: 41 | tag_name: ${{ github.ref }} 42 | release_name: ${{ github.ref }} 43 | draft: false 44 | prerelease: false 45 | # Upload the packaged release file 46 | - name: Upload zip file 47 | id: upload-zip 48 | uses: actions/upload-release-asset@v1 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | with: 52 | upload_url: ${{ steps.create_release.outputs.upload_url }} 53 | asset_path: ./${{ github.event.repository.name }}.zip 54 | asset_name: ${{ github.event.repository.name }}-${{ steps.version.outputs.tag }}.zip 55 | asset_content_type: application/zip 56 | # Upload the main.js 57 | - name: Upload main.js 58 | id: upload-main 59 | uses: actions/upload-release-asset@v1 60 | env: 61 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 62 | with: 63 | upload_url: ${{ steps.create_release.outputs.upload_url }} 64 | asset_path: ./main.js 65 | asset_name: main.js 66 | asset_content_type: text/javascript 67 | # Upload the manifest.json 68 | - name: Upload manifest.json 69 | id: upload-manifest 70 | uses: actions/upload-release-asset@v1 71 | env: 72 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 73 | with: 74 | upload_url: ${{ steps.create_release.outputs.upload_url }} 75 | asset_path: ./manifest.json 76 | asset_name: manifest.json 77 | asset_content_type: application/json 78 | # Upload the styles.css 79 | - name: Upload styles.css 80 | id: upload-styles 81 | uses: actions/upload-release-asset@v1 82 | env: 83 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 84 | with: 85 | upload_url: ${{ steps.create_release.outputs.upload_url }} 86 | asset_path: ./styles.css 87 | asset_name: styles.css 88 | asset_content_type: text/css 89 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Intellij 2 | *.iml 3 | .idea 4 | 5 | # npm 6 | node_modules 7 | package-lock.json 8 | 9 | # build 10 | main.js 11 | *.js.map 12 | 13 | .DS_Store -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All changes to this plugin are listed here. 4 | 5 | ## 1.0.1 (2024-06-18) 6 | 7 | ### Fixed 8 | - #14 No yaml field values without a "toString" method 9 | 10 | ## 1.0.0 (2024-06-16) 11 | 12 | ### New 13 | 14 | - Use variables in all fields 15 | - #13 Use variables from the properties (only first level of properties) 16 | 17 | ## 0.6.0 (2023-08-17) 18 | 19 | ### New 20 | 21 | - #7 Small UI improvements with new MailTo Button 22 | 23 | ## 0.5.0 (2023-07-01) 24 | 25 | ### New 26 | 27 | - #8 Add a **from** parameter. 28 | 29 | ## 0.4.0 (2023-06-09) 30 | 31 | ### New 32 | 33 | - #4 Body can be set after the yaml, seperated by a "---" line 34 | 35 | ## 0.3.3 (2023-03-06) 36 | 37 | ### Fixed 38 | 39 | - #2 only add `&cc`, `&bcc` or `&body` if a value is provided 40 | 41 | ## 0.3.2 (2023-01-13) 42 | 43 | ### Fixed 44 | 45 | - Use `"""` for second parameter in `getFirstLinkpathDest` if absolute path 46 | 47 | ## 0.3.1 (2023-01-12) 48 | 49 | ### Fixed 50 | 51 | - Use `ctx.sourcePath` for finding the correct frontmatter data of the file 52 | - Use `ctx.sourcePath` in `getFirstLinkpathDest` to make sure finding the correct linked file 53 | 54 | ## 0.3.0 (2023-01-04) 55 | 56 | ### New 57 | 58 | - Add placeholder variables 59 | 60 | ## 0.2.0 (2022-12-30) 61 | 62 | ### New 63 | 64 | - A note can be used as body content using an internal link. 65 | 66 | ## 0.1.1 (2022-12-28) 67 | 68 | ### Changed 69 | 70 | - Use obsidian parseYaml 71 | 72 | ## 0.1.0 (2022-12-17) 73 | 74 | ### Added 75 | 76 | - Base functionality -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Jonas Blatt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Email Block for Obsidian [![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/joleaf/obsidian-email-block-plugin)](https://github.com/joleaf/obsidian-email-block-plugin/releases) [![Release Obsidian Plugin](https://github.com/joleaf/obsidian-email-block-plugin/actions/workflows/release.yml/badge.svg)](https://github.com/joleaf/obsidian-email-block-plugin/actions/workflows/release.yml) [![Obsidian downloads](https://img.shields.io/badge/dynamic/json?logo=obsidian&color=%238b6cef&label=downloads&query=%24%5B%22email-block-plugin%22%5D.downloads&url=https%3A%2F%2Fraw.githubusercontent.com%2Fobsidianmd%2Fobsidian-releases%2Fmaster%2Fcommunity-plugin-stats.json)](https://obsidian.md/plugins?id=email-block-plugin) 2 | 3 | This plugin lets you plan small emails inside your [Obsidian](https://www.obsidian.md) notes. 4 | 5 | ## Install .. 6 | 7 | ### .. automatically in Obsidian 8 | 9 | 1. Go to **Community Plugins** in your Obsidian Settings and **disable** Safe Mode 10 | 2. Click on **Browse** and search for "Email Block" 11 | 3. Click install 12 | 4. Toggle the plugin on in the **Community Plugins** tab 13 | 14 | ### .. manually from this repo 15 | 16 | 1. Download the latest [release](https://github.com/joleaf/obsidian-email-block-plugin/releases) `*.zip` file. 17 | 2. Unpack the zip in the `.obsidan/plugins` folder of your obsidian vault 18 | 19 | ## How to use 20 | 21 | Add the "email" code block into your note: 22 | 23 | ... with plain text as body content: 24 | 25 | ```` 26 | ```email 27 | to: info@randommail.com 28 | subject: My Subject 29 | body: "Hey info, 30 | 31 | here is some content" 32 | ``` 33 | ```` 34 | 35 | ... with a referenced note as body content: 36 | 37 | ```` 38 | ```email 39 | to: info@randommail.com 40 | subject: My Subject 41 | body: [[MyMail4711]] 42 | variables: 43 | myvar: TestVar 44 | ``` 45 | ```` 46 | 47 | You can use the `variables` parameter to replace placeholders in your body text with the variable values. 48 | To include a variable in the body text just add a placeholder `{{myvar}}`. 49 | Variables from fontmatter data can be used as well. 50 | 51 | ... with a body text after the yaml: 52 | 53 | ```` 54 | ```email 55 | to: info@randommail.com 56 | subject: Hello World 57 | --- 58 | Hi there, 59 | this is my new body 60 | Best! 61 | JB 62 | ``` 63 | ```` 64 | 65 | ... you can use properties, like variables, on the subject or within the body: 66 | 67 | ```` 68 | ```email 69 | to: info@randommail.com 70 | subject: reminder for {{name}} 71 | --- 72 | Dear {{name}}, 73 | this is not a personal email. 74 | Regards, 75 | FI 76 | ``` 77 | ```` 78 | 79 | ### Parameter 80 | 81 | You can customize the view with the following parameters: 82 | 83 | | Parameter | Description | Values | Required | 84 | |------------|------------------------------------------------------------------------|--------------------------------|----------| 85 | | to | The main receiver of the mail. Multiple receiver seperated by ",". | String / List of Strings | | 86 | | cc | The cc receiver of the mail. Multiple receiver seperated by ",". | String / List of Strings | | 87 | | bcc | The bcc receiver of the mail. Multiple receiver seperated by ",". | String value / List of Strings | | 88 | | subject | The subject of the email. Plain text or combined text with variables | String value | x | 89 | | body (1) | The body of the email. Plain text or a link to a \[\[NoteFile\]\] (2). | String value | x | 90 | | showmailto | Show the "mailto" link after the mail body. | true/false (Default: true) | | 91 | | variables | A map of placeholder variables. | YAML Object | | 92 | | from | A from field (only for documentation). | String value | | 93 | 94 | 1) The body can be appended after the yaml with a "---" separation 95 | 2) No formatting is supported (only new 96 | lines) ([reason](https://stackoverflow.com/questions/5620324/mailto-link-with-html-body)). 97 | 98 | ### Example 99 | 100 | ![Example](example/email-block-plugin.gif) 101 | 102 | ## How to dev 103 | 104 | 1. Clone this repo into the plugin folder of a (non-productive) vault (`.obsidian/plugins/`) 105 | 2. `npm i` 106 | 3. `npm run dev` 107 | 4. Toggle the plugin on in the **Community Plugins** tab 108 | 109 | ## Contributors 110 | Thank you for your contributions! 111 | - [Vrum89](https://github.com/Vrum89) 112 | - [xxie-xd](https://github.com/) 113 | 114 | ## Donate 115 | 116 | Buy Me a Coffee at ko-fi.com 117 | -------------------------------------------------------------------------------- /esbuild.config.mjs: -------------------------------------------------------------------------------- 1 | import esbuild from "esbuild"; 2 | import process from "process"; 3 | import builtins from 'builtin-modules' 4 | 5 | const banner = 6 | `/* 7 | THIS IS A GENERATED/BUNDLED FILE BY ESBUILD 8 | if you want to view the source, please visit the github repository of this plugin 9 | */ 10 | `; 11 | 12 | const prod = (process.argv[2] === 'production'); 13 | 14 | esbuild.build({ 15 | banner: { 16 | js: banner, 17 | }, 18 | entryPoints: ['main.ts'], 19 | bundle: true, 20 | external: [ 21 | 'obsidian', 22 | 'electron', 23 | '@codemirror/autocomplete', 24 | '@codemirror/collab', 25 | '@codemirror/commands', 26 | '@codemirror/language', 27 | '@codemirror/lint', 28 | '@codemirror/search', 29 | '@codemirror/state', 30 | '@codemirror/view', 31 | '@lezer/common', 32 | '@lezer/highlight', 33 | '@lezer/lr', 34 | ...builtins], 35 | format: 'cjs', 36 | watch: !prod, 37 | target: 'es2018', 38 | logLevel: "info", 39 | sourcemap: prod ? false : 'inline', 40 | treeShaking: true, 41 | outfile: 'main.js', 42 | }).catch(() => process.exit(1)); -------------------------------------------------------------------------------- /example/email-block-plugin.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joleaf/obsidian-email-block-plugin/f3a033a71316e19ae7c85d4dbc300d1af72dd92c/example/email-block-plugin.gif -------------------------------------------------------------------------------- /main.ts: -------------------------------------------------------------------------------- 1 | import {Plugin, parseYaml, MarkdownRenderer, Component, MarkdownPostProcessorContext, setIcon} from "obsidian"; 2 | 3 | interface MailBlockParameters { 4 | to: [string] | string | undefined; 5 | cc: [string] | string | undefined; 6 | bcc: [string] | string | undefined; 7 | subject: string | undefined; 8 | body: string | undefined; 9 | showmailto: boolean | undefined; 10 | variables: { [name: string]: string | undefined } 11 | from: string | undefined; 12 | } 13 | 14 | export default class MailBlockPlugin extends Plugin { 15 | 16 | async onload() { 17 | console.log("email block loading..."); 18 | 19 | this.registerMarkdownCodeBlockProcessor("email", async (src, el, ctx) => { 20 | // Get Parameters 21 | let parameters: MailBlockParameters | null = null; 22 | try { 23 | parameters = this.readParameters(src, ctx); 24 | } catch (e) { 25 | el.createEl("h3", {text: "Email parameters invalid: \n" + e.message}); 26 | return; 27 | } 28 | 29 | // console.log("Render the Email " + parameters); 30 | try { 31 | const rootEl = el.createEl("div", {cls: "email-block email-block-border"}); 32 | 33 | let fromContent = undefined; 34 | if (parameters.from !== undefined) { 35 | rootEl.createEl("div", {cls: "email-block-info", text: "From:"}); 36 | fromContent = this.replaceVariables(this.renderAddress(parameters.from), parameters.variables) 37 | rootEl.createEl("div", {cls: "email-block-info-value", text: fromContent}); 38 | } 39 | let toContent = undefined; 40 | if (parameters.to !== undefined) { 41 | rootEl.createEl("div", {cls: "email-block-info", text: "To:"}); 42 | toContent = this.replaceVariables(this.renderAddress(parameters.to), parameters.variables) 43 | rootEl.createEl("div", {cls: "email-block-info-value", text: toContent}); 44 | } 45 | let ccContent = undefined; 46 | if (parameters.cc !== undefined) { 47 | rootEl.createEl("div", {cls: "email-block-info", text: "Cc:"}); 48 | ccContent = this.replaceVariables(this.renderAddress(parameters.cc), parameters.variables) 49 | rootEl.createEl("div", {cls: "email-block-info-value", text: ccContent}); 50 | } 51 | let bccContent = undefined; 52 | if (parameters.bcc !== undefined) { 53 | rootEl.createEl("div", {cls: "email-block-info", text: "Bcc:"}); 54 | bccContent = this.replaceVariables(this.renderAddress(parameters.bcc), parameters.variables) 55 | rootEl.createEl("div", {cls: "email-block-info-value", text: bccContent}); 56 | } 57 | rootEl.createEl("div", {cls: "email-block-info", text: "Subject:"}); 58 | const subjectContent = this.replaceVariables(parameters.subject, parameters.variables); 59 | rootEl.createEl("div", {cls: "email-block-info-value", text: subjectContent}); 60 | 61 | const bodyContent = rootEl.createEl("div", {cls: "email-block-body"}); 62 | await this.renderBody(bodyContent, parameters.body, parameters.variables, ctx); 63 | if (parameters.showmailto) { 64 | const data = "mailto:" + this.encodeToHtml(toContent) + 65 | "?subject=" + this.encodeToHtml(subjectContent) + 66 | (ccContent !== undefined ? "&cc=" + this.encodeToHtml(ccContent) : "") + 67 | (bccContent !== undefined ? "&bcc=" + this.encodeToHtml(bccContent) : "") + 68 | (bodyContent.innerText.length !== 0 ? "&body=" + this.encodeToHtml(bodyContent.innerText) : ""); 69 | const mailToButton = rootEl 70 | .createEl("div", {cls: "email-block-mailto"}) 71 | .createEl("a", {href: data, text: "Mailto"}); 72 | setIcon(mailToButton, "mail"); 73 | } 74 | 75 | } catch (error) { 76 | el.createEl("h3", {text: error}); 77 | } 78 | }); 79 | } 80 | 81 | 82 | private readParameters(yamlString: string, ctx: MarkdownPostProcessorContext) { 83 | if (yamlString.contains("[[") && !yamlString.contains('"[[')) { 84 | yamlString = yamlString.replace("[[", '"[['); 85 | yamlString = yamlString.replace("]]", ']]"'); 86 | } 87 | let extraBody = ""; 88 | if (yamlString.contains("---")) { 89 | let data = yamlString.split("---"); 90 | yamlString = data[0]; 91 | extraBody = data[1]; 92 | } 93 | 94 | //Necessary to do not parse {{value}} into on object by parseYaml 95 | if (yamlString.contains("{{") && !yamlString.contains('"{{')) { 96 | yamlString = yamlString.replace("{{", '"{{'); 97 | yamlString = yamlString.replace("}}", '}}"'); 98 | } 99 | 100 | const parameters: MailBlockParameters = parseYaml(yamlString); 101 | 102 | parameters.to = this.fixAddress(parameters.to); 103 | parameters.cc = this.fixAddress(parameters.cc); 104 | parameters.bcc = this.fixAddress(parameters.bcc); 105 | 106 | if (parameters.subject == undefined) { 107 | parameters.subject = ""; 108 | } else { 109 | //remove double quotes (it has been utilized after parsing) 110 | parameters.subject = parameters.subject.replace('"{{', "{{"); 111 | parameters.subject = parameters.subject.replace('}}"', "}}"); 112 | } 113 | 114 | if (parameters.showmailto == undefined) { 115 | parameters.showmailto = true; 116 | } 117 | 118 | if (parameters.body === undefined) { 119 | parameters.body = extraBody; 120 | } 121 | 122 | // Variables 123 | if (parameters.variables === undefined) { 124 | parameters.variables = {}; 125 | } 126 | const sourceFile = this.app.metadataCache.getFirstLinkpathDest( 127 | ctx.sourcePath, 128 | "", 129 | ); 130 | if (sourceFile != null) { 131 | const sourceCache = this.app.metadataCache.getFileCache(sourceFile); 132 | if (sourceCache != null) { 133 | if (sourceCache.frontmatter != undefined) { 134 | for (const [key, value] of Object.entries(sourceCache.frontmatter)) { 135 | if (value && typeof value.toString === 'function') { 136 | parameters.variables[key] = value.toString(); 137 | } 138 | } 139 | } 140 | } 141 | } 142 | return parameters; 143 | } 144 | 145 | private fixAddress(address: [string] | string | undefined) { 146 | if (address === undefined) { 147 | return undefined; 148 | } 149 | let fixedAddress: string = ""; 150 | if (Array.isArray(address)) { 151 | fixedAddress = address.join(","); 152 | } else { 153 | fixedAddress = address; 154 | } 155 | fixedAddress = fixedAddress.replace(/\s/g, "").replace(";", ","); 156 | return fixedAddress; 157 | } 158 | 159 | private renderAddress(address: [string] | string) { 160 | if (Array.isArray(address)) { 161 | return address.join(", ") 162 | } 163 | return address.split(",").join(", "); 164 | } 165 | 166 | private async renderBody(bodyContentEl: HTMLElement, bodyContent: string | undefined, variables: { 167 | [name: string]: string | undefined 168 | }, ctx: MarkdownPostProcessorContext) { 169 | if (bodyContent === undefined) { 170 | return; 171 | } 172 | // render a markdown file 173 | if (bodyContent.startsWith("[[")) { 174 | bodyContent = bodyContent.substring(2, bodyContent.length - 2); 175 | 176 | const mdFile = this.app.metadataCache.getFirstLinkpathDest( 177 | bodyContent, 178 | ctx.sourcePath 179 | ); 180 | if (mdFile != null) { 181 | let mdContent = await this.app.vault.read(mdFile); 182 | mdContent = this.replaceVariables(mdContent, variables); 183 | await MarkdownRenderer.renderMarkdown(mdContent, bodyContentEl, mdFile.path, new Component()); 184 | } 185 | } else { // Render line by line as plain text 186 | bodyContent = this.replaceVariables(bodyContent, variables); 187 | let lines = bodyContent.split("\n"); 188 | lines.forEach(line => { 189 | bodyContentEl.createEl("div", {cls: "email-block-body-line", text: line}); 190 | }) 191 | } 192 | } 193 | 194 | private replaceVariables(content: string | undefined, variables: { [name: string]: string | undefined }): string { 195 | if (content === undefined) { 196 | return ""; 197 | } 198 | let resultingContent = content; 199 | for (const [variable, value] of Object.entries(variables)) { 200 | if (value != undefined) { 201 | resultingContent = resultingContent?.replace("{{" + variable + "}}", value); 202 | } 203 | } 204 | return resultingContent; 205 | } 206 | 207 | private encodeToHtml(rawStr: string | undefined) { 208 | if (rawStr === undefined) { 209 | return ""; 210 | } 211 | return encodeURIComponent(rawStr); 212 | } 213 | 214 | onunload() { 215 | console.log("Unloading email plugin..."); 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "email-block-plugin", 3 | "name": "Email code block", 4 | "version": "1.0.1", 5 | "minAppVersion": "0.15.0", 6 | "description": "This plugin renders an email code block.", 7 | "author": "JoLeaf", 8 | "authorUrl": "https://github.com/JoLeaf", 9 | "fundingUrl": "https://ko-fi.com/joleaf", 10 | "isDesktopOnly": false 11 | } 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "email-block-plugin", 3 | "version": "1.0.1", 4 | "description": "This plugin renders an email code block.", 5 | "main": "main.js", 6 | "scripts": { 7 | "dev": "node esbuild.config.mjs", 8 | "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", 9 | "version": "node version-bump.mjs && git add manifest.json versions.json" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "MIT", 14 | "devDependencies": { 15 | "@types/node": "^16.11.6", 16 | "@typescript-eslint/eslint-plugin": "5.29.0", 17 | "@typescript-eslint/parser": "5.29.0", 18 | "builtin-modules": "3.3.0", 19 | "esbuild": "0.14.47", 20 | "obsidian": "latest", 21 | "tslib": "2.4.0", 22 | "typescript": "4.7.4" 23 | }, 24 | "dependencies": { 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | /* Styles */ 2 | 3 | .email-block { 4 | display: grid; 5 | grid-template-columns: 1fr 6fr; 6 | row-gap: 4px; 7 | padding: 4px; 8 | } 9 | 10 | .email-block-border { 11 | border: 1px solid gray; 12 | border-radius: 5px; 13 | } 14 | 15 | .email-block-info { 16 | font-style: italic; 17 | font-size: 80%; 18 | align-self: center; 19 | } 20 | 21 | .email-block-info-value { 22 | font-size: 90%; 23 | align-self: center; 24 | } 25 | 26 | .email-block-body { 27 | grid-column-start: 1; 28 | grid-column-end: span 2; 29 | border-left: 2px gray solid; 30 | padding-left: 5px; 31 | } 32 | 33 | .email-block-body-line { 34 | 35 | } 36 | 37 | .email-block-mailto { 38 | grid-column-start: 1; 39 | grid-row-start: 1; 40 | grid-column-end: span 2; 41 | --icon-size: 2rem; 42 | } 43 | 44 | .email-block-error { 45 | color: red !important; 46 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "inlineSourceMap": true, 5 | "inlineSources": true, 6 | "module": "ESNext", 7 | "target": "ES6", 8 | "allowJs": true, 9 | "noImplicitAny": true, 10 | "moduleResolution": "node", 11 | "importHelpers": true, 12 | "isolatedModules": true, 13 | "strictNullChecks": true, 14 | "lib": [ 15 | "DOM", 16 | "ES5", 17 | "ES6", 18 | "ES7" 19 | ], 20 | "allowSyntheticDefaultImports": true 21 | }, 22 | "include": [ 23 | "**/*.ts" 24 | ], 25 | "typeRoots": [ 26 | "./typings", 27 | "./node_modules/@types/" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "0.1.0": "0.15.0", 3 | "0.1.1": "0.15.0", 4 | "0.2.0": "0.15.0", 5 | "0.3.0": "0.15.0", 6 | "0.3.1": "0.15.0", 7 | "0.3.2": "0.15.0", 8 | "0.3.3": "0.15.0", 9 | "0.4.0": "0.15.0", 10 | "0.5.0": "0.15.0", 11 | "0.6.0": "0.15.0", 12 | "1.0.0": "0.15.0", 13 | "1.0.1": "0.15.0" 14 | } 15 | --------------------------------------------------------------------------------